aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/utils
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-09-08 14:07:41 +0200
committerBjörn Gustavsson <[email protected]>2017-09-13 11:47:41 +0200
commita58daf5c38b4921c82008c811cd5dd178deef49f (patch)
treeba21d46eb74cf17a08a4746f212e9d82da1126c2 /erts/emulator/utils
parent7471c87214aec6f28a9fba2bf0356b45ee717d33 (diff)
downloadotp-a58daf5c38b4921c82008c811cd5dd178deef49f.tar.gz
otp-a58daf5c38b4921c82008c811cd5dd178deef49f.tar.bz2
otp-a58daf5c38b4921c82008c811cd5dd178deef49f.zip
Add built-in macros $ARG_POSITION() and $IS_PACKED()
Diffstat (limited to 'erts/emulator/utils')
-rwxr-xr-xerts/emulator/utils/beam_makeops55
1 files changed, 44 insertions, 11 deletions
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index e55d3eadb5..8e34e07035 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -268,6 +268,16 @@ if ($wordsize == 64) {
}
#
+# Add placeholders for built-in macros.
+#
+
+$c_code{'IS_PACKED'} = ['$Expr',"built-in macro",('Expr')];
+$c_code{'ARG_POSITION'} = ['$Expr',"built-in macro",('Expr')];
+foreach my $name (keys %c_code) {
+ $c_code_used{$name} = 1;
+}
+
+#
# Parse the input files.
#
@@ -1382,14 +1392,8 @@ sub expand_all {
my $keep = substr($code, 0, $-[0]);
my $after = substr($code, $+[0]);
- # Keep the special, pre-defined bindings.
- my %new_bindings;
- foreach my $key (qw(NEXT_INSTRUCTION)) {
- $new_bindings{$key} = $bindings{$key};
- }
-
my $body;
- ($body,$code) = expand_macro($macro_name, $after, \%new_bindings);
+ ($body,$code) = expand_macro($macro_name, $after, \%bindings);
$res .= "$keep$body";
}
@@ -1436,21 +1440,49 @@ sub expand_macro {
$arg =~ s/^\s*//;
}
- # Now combine bindings from the parameter names and arguments.
- my %bindings = %{$bindings_ref};
+ # Make sure that the number of arguments are correct.
if (@vars != @args) {
error("calling $name with ", scalar(@args),
" arguments instead of expected ", scalar(@vars), " arguments...");
}
+
+ # Now combine bindings from the parameter names and arguments.
+ my %bindings = %{$bindings_ref};
+ my %new_bindings;
+
+ # Keep the special, pre-defined bindings.
+ foreach my $key (qw(NEXT_INSTRUCTION)) {
+ $new_bindings{$key} = $bindings{$key};
+ }
+
for (my $i = 0; $i < @vars; $i++) {
- $bindings{$vars[$i]} = $args[$i];
+ my $arg = $args[$i];
+ $arg = eval { expand_all($arg, \%bindings) };
+ unless (defined $arg) {
+ warn $@;
+ die "... from the body of $name at $where\n";
+ }
+ $new_bindings{$vars[$i]} = $arg;
}
- $body = eval { expand_all($body, \%bindings) };
+ $body = eval { expand_all($body, \%new_bindings) };
unless (defined $body) {
warn $@;
die "... from the body of $name at $where\n";
}
+
+ # Handle built-in macros.
+ if ($name eq 'ARG_POSITION') {
+ if ($body =~ /^I\[(\d+)\]$/) {
+ $body = $1;
+ } else {
+ $body = 0;
+ }
+ } elsif ($name eq 'IS_PACKED') {
+ $body = ($body =~ /^I\[\d+\]$/) ? 0 : 1;
+ }
+
+ # Wrap body if needed and return resul.t
$body = "do {\n$body\n} while (0)"
if needs_do_wrapper($body);
($body,$rest);
@@ -1476,6 +1508,7 @@ sub needs_do_wrapper {
return 0 if /^[A-Z_]*SWAPOUT/;
return 0 if /^if\s*[(]/;
return 0 if /^goto\b/;
+ return 0 if /^\d+/;
return 1; # Not sure, say that it is needed.
}