PageRenderTime 63ms CodeModel.GetById 11ms RepoModel.GetById 2ms app.codeStats 0ms

/erts/emulator/utils/beam_makeops

https://github.com/notarf/otp
Perl | 1727 lines | 1278 code | 216 blank | 233 comment | 155 complexity | 30dd9d3f0499c248050b33f6b81b2ab9 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. #!/usr/bin/env perl
  2. #
  3. # %CopyrightBegin%
  4. #
  5. # Copyright Ericsson AB 1998-2011. All Rights Reserved.
  6. #
  7. # The contents of this file are subject to the Erlang Public License,
  8. # Version 1.1, (the "License"); you may not use this file except in
  9. # compliance with the License. You should have received a copy of the
  10. # Erlang Public License along with this software. If not, it can be
  11. # retrieved online at http://www.erlang.org/.
  12. #
  13. # Software distributed under the License is distributed on an "AS IS"
  14. # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  15. # the License for the specific language governing rights and limitations
  16. # under the License.
  17. #
  18. # %CopyrightEnd%
  19. #
  20. use strict;
  21. use vars qw($BEAM_FORMAT_NUMBER);
  22. $BEAM_FORMAT_NUMBER = undef;
  23. my $target = \&emulator_output;
  24. my $outdir = "."; # Directory for output files.
  25. my $verbose = 0;
  26. my $hot = 1;
  27. my $num_file_opcodes = 0;
  28. my $wordsize = 32;
  29. # This is shift counts and mask for the packer.
  30. my $WHOLE_WORD = '';
  31. my @pack_instr;
  32. my @pack_shift;
  33. my @pack_mask;
  34. $pack_instr[2] = ['6', 'i'];
  35. $pack_instr[3] = ['0', '0', 'i'];
  36. $pack_instr[4] = ['6', '6', '6', 'i']; # Only for 64 bit wordsize
  37. $pack_shift[2] = ['0', 'BEAM_LOOSE_SHIFT'];
  38. $pack_shift[3] = ['0', 'BEAM_TIGHT_SHIFT', '(2*BEAM_TIGHT_SHIFT)'];
  39. $pack_shift[4] = ['0', 'BEAM_LOOSE_SHIFT', # Only for 64 bit wordsize
  40. '(2*BEAM_LOOSE_SHIFT)',
  41. '(3*BEAM_LOOSE_SHIFT)'];
  42. $pack_mask[2] = ['BEAM_LOOSE_MASK', $WHOLE_WORD];
  43. $pack_mask[3] = ['BEAM_TIGHT_MASK', 'BEAM_TIGHT_MASK', 'BEAM_TIGHT_MASK'];
  44. $pack_mask[4] = ['BEAM_LOOSE_MASK', # Only for 64 bit wordsize
  45. 'BEAM_LOOSE_MASK',
  46. 'BEAM_LOOSE_MASK',
  47. $WHOLE_WORD];
  48. # There are two types of instructions: generic and specific.
  49. # The generic instructions are those generated by the Beam compiler.
  50. # Corresponding to each generic instruction, there is generally a
  51. # whole family of related specific instructions. Specific instructions
  52. # are those executed by the VM interpreter during run-time.
  53. # Maximum number of operands for a generic instruction.
  54. # In beam_load.c the MAX_OPARGS refers to the maximum
  55. # number of operands for generic instructions.
  56. my $max_gen_operands = 8;
  57. # Maximum number of operands for a specific instruction.
  58. # Must be even. The beam_load.c file must be updated, too.
  59. my $max_spec_operands = 6;
  60. # The maximum number of primitive genop_types.
  61. my $max_genop_types = 16;
  62. my %gen_opnum;
  63. my %num_specific;
  64. my %gen_to_spec;
  65. my %specific_op;
  66. my %gen_arity;
  67. my @gen_arity;
  68. my @gen_opname;
  69. my @op_to_name;
  70. my @obsolete;
  71. my %macro;
  72. my %macro_flags;
  73. my %hot_code;
  74. my %cold_code;
  75. my @unnumbered_generic;
  76. my %unnumbered;
  77. my %is_transformed;
  78. #
  79. # Code transformations.
  80. #
  81. my $te_max_vars = 0; # Max number of variables ever needed.
  82. my %gen_transform;
  83. my %min_window;
  84. my %match_engine_ops; # All opcodes for the match engine.
  85. my %gen_transform_offset;
  86. my @transformations;
  87. my @call_table;
  88. my %call_table;
  89. my @pred_table;
  90. my %pred_table;
  91. # Operand types for generic instructions.
  92. my $compiler_types = "uiaxyfhz";
  93. my $loader_types = "nprvlqo";
  94. my $genop_types = $compiler_types . $loader_types;
  95. #
  96. # Defines the argument types and their loaded size assuming no packing.
  97. #
  98. my %arg_size = ('r' => 0, # x(0) - x register zero
  99. 'x' => 1, # x(N), N > 0 - x register
  100. 'y' => 1, # y(N) - y register
  101. 'i' => 1, # tagged integer
  102. 'a' => 1, # tagged atom
  103. 'n' => 0, # NIL (implicit)
  104. 'c' => 1, # tagged constant (integer, atom, nil)
  105. 's' => 1, # tagged source; any of the above
  106. 'd' => 1, # tagged destination register (r, x, y)
  107. 'f' => 1, # failure label
  108. 'j' => 1, # either 'f' or 'p'
  109. 'e' => 1, # pointer to export entry
  110. 'L' => 0, # label
  111. 'I' => 1, # untagged integer
  112. 't' => 1, # untagged integer -- can be packed
  113. 'b' => 1, # pointer to bif
  114. 'A' => 1, # arity value
  115. 'P' => 1, # byte offset into tuple or stack
  116. 'Q' => 1, # like 'P', but packable
  117. 'h' => 1, # character
  118. 'l' => 1, # float reg
  119. 'q' => 1, # literal term
  120. );
  121. #
  122. # Generate bits.
  123. #
  124. my %type_bit;
  125. my @tag_type;
  126. sub define_type_bit {
  127. my($tag,$val) = @_;
  128. defined $type_bit{$tag} and
  129. sanity("the tag '$tag' has already been defined with the value ",
  130. $type_bit{$tag});
  131. $type_bit{$tag} = $val;
  132. }
  133. {
  134. my($bit) = 1;
  135. my(%bit);
  136. foreach (split('', $genop_types)) {
  137. push(@tag_type, $_);
  138. define_type_bit($_, $bit);
  139. $bit{$_} = $bit;
  140. $bit *= 2;
  141. }
  142. # Composed types.
  143. define_type_bit('d', $type_bit{'x'} | $type_bit{'y'} | $type_bit{'r'});
  144. define_type_bit('c', $type_bit{'i'} | $type_bit{'a'} |
  145. $type_bit{'n'} | $type_bit{'q'});
  146. define_type_bit('s', $type_bit{'d'} | $type_bit{'i'} |
  147. $type_bit{'a'} | $type_bit{'n'});
  148. define_type_bit('j', $type_bit{'f'} | $type_bit{'p'});
  149. # Aliases (for matching purposes).
  150. define_type_bit('I', $type_bit{'u'});
  151. define_type_bit('t', $type_bit{'u'});
  152. define_type_bit('A', $type_bit{'u'});
  153. define_type_bit('L', $type_bit{'u'});
  154. define_type_bit('b', $type_bit{'u'});
  155. define_type_bit('N', $type_bit{'u'});
  156. define_type_bit('U', $type_bit{'u'});
  157. define_type_bit('e', $type_bit{'u'});
  158. define_type_bit('P', $type_bit{'u'});
  159. define_type_bit('Q', $type_bit{'u'});
  160. }
  161. #
  162. # Pre-define the 'fail' instruction. It is used internally
  163. # by the 'try_me_else_fail' instruction.
  164. #
  165. $match_engine_ops{'TOP_fail'} = 1;
  166. #
  167. # Sanity checks.
  168. #
  169. {
  170. if (@tag_type > $max_genop_types) {
  171. sanity("\$max_genop_types is $max_genop_types, ",
  172. "but there are ", scalar(@tag_type),
  173. " primitive tags defined\n");
  174. }
  175. foreach my $tag (@tag_type) {
  176. sanity("tag '$tag': primitive tags must be named with lowercase letters")
  177. unless $tag =~ /^[a-z]$/;
  178. }
  179. }
  180. #
  181. # Parse command line options.
  182. #
  183. while (@ARGV && $ARGV[0] =~ /^-(.*)/) {
  184. $_ = $1;
  185. shift;
  186. ($target = \&emulator_output), next if /^emulator/;
  187. ($target = \&compiler_output), next if /^compiler/;
  188. ($outdir = shift), next if /^outdir/;
  189. ($wordsize = shift), next if /^wordsize/;
  190. ($verbose = 1), next if /^v/;
  191. die "$0: Bad option: -$_\n";
  192. }
  193. #
  194. # Parse the input files.
  195. #
  196. while (<>) {
  197. my($op_num);
  198. chomp;
  199. if (s/\\$//) {
  200. $_ .= <>;
  201. redo unless eof(ARGV);
  202. }
  203. next if /^\s*$/;
  204. next if /^\#/;
  205. #
  206. # Handle assignments.
  207. #
  208. if (/^([\w_][\w\d_]+)=(.*)/) {
  209. no strict 'refs';
  210. my($name) = $1;
  211. $$name = $2;
  212. next;
  213. }
  214. #
  215. # Handle %hot/%cold.
  216. #
  217. if (/^\%hot/) {
  218. $hot = 1;
  219. next;
  220. } elsif (/^\%cold/) {
  221. $hot = 0;
  222. next;
  223. }
  224. #
  225. # Handle macro definitions.
  226. #
  227. if (/^\%macro:(.*)/) {
  228. my($op, $macro, @flags) = split(' ', $1);
  229. defined($macro) and $macro =~ /^-/ and
  230. &error("A macro must not start with a hyphen");
  231. foreach (@flags) {
  232. /^-/ or &error("Flags for macros should start with a hyphen");
  233. }
  234. error("Macro for '$op' is already defined")
  235. if defined $macro{$op};
  236. $macro{$op} = $macro;
  237. $macro_flags{$op} = join('', @flags);
  238. next;
  239. }
  240. #
  241. # Handle transformations.
  242. #
  243. if (/=>/) {
  244. &parse_transformation($_);
  245. next;
  246. }
  247. #
  248. # Parse off the number of the operation.
  249. #
  250. $op_num = undef;
  251. if (s/^(\d+):\s*//) {
  252. $op_num = $1;
  253. $op_num != 0 or &error("Opcode 0 invalid");
  254. &error("Opcode $op_num already defined")
  255. if defined $gen_opname[$op_num];
  256. }
  257. #
  258. # Parse: Name/Arity (generic instruction)
  259. #
  260. if (m@^(-)?(\w+)/(\d)\s*$@) {
  261. my($obsolete) = $1;
  262. my($name) = $2;
  263. my($arity) = $3;
  264. $name =~ /^[a-z]/ or &error("Opname must start with a lowercase letter");
  265. defined $gen_arity{$name} and $gen_arity{$name} != $arity and
  266. &error("Opname $name already defined with arity $gen_arity{$name}");
  267. defined $unnumbered{$name,$arity} and
  268. &error("Opname $name already defined with arity $gen_arity{$name}");
  269. if (defined $op_num) { # Numbered generic operation
  270. $gen_opname[$op_num] = $name;
  271. $gen_arity[$op_num] = $arity;
  272. $gen_opnum{$name,$arity} = $op_num;
  273. $gen_arity{$name} = $arity;
  274. $gen_to_spec{"$name/$arity"} = undef;
  275. $num_specific{"$name/$arity"} = 0;
  276. $min_window{"$name/$arity"} = 255;
  277. $obsolete[$op_num] = $obsolete eq '-';
  278. } else { # Unnumbered generic operation.
  279. push(@unnumbered_generic, [$name, $arity]);
  280. $unnumbered{$name,$arity} = 1;
  281. }
  282. next;
  283. }
  284. #
  285. # Parse specific instructions (only present in emulator/loader):
  286. # Name Arg1 Arg2...
  287. #
  288. my($name, @args) = split;
  289. &error("too many operands")
  290. if @args > $max_spec_operands;
  291. &syntax_check($name, @args);
  292. my $arity = @args;
  293. if ($obsolete[$gen_opnum{$name,$arity}]) {
  294. error("specific instructions may not be specified for obsolete instructions");
  295. }
  296. push(@{$specific_op{"$name/$arity"}}, [$name, $hot, @args]);
  297. if (defined $op_num) {
  298. &error("specific instructions must not be numbered");
  299. } elsif (!defined($gen_arity{$name}) && !defined($unnumbered{$name,$arity})) {
  300. #
  301. # Create an unumbered generic instruction too.
  302. #
  303. push(@unnumbered_generic, [$name, $arity]);
  304. $unnumbered{$name,$arity} = 1;
  305. }
  306. } continue {
  307. close(ARGV) if eof(ARGV);
  308. }
  309. $num_file_opcodes = @gen_opname;
  310. #
  311. # Number all generic operations without numbers.
  312. #
  313. {
  314. my $ref;
  315. foreach $ref (@unnumbered_generic) {
  316. my($name, $arity) = @$ref;
  317. my $op_num = @gen_opname;
  318. push(@gen_opname, $name);
  319. push(@gen_arity, $arity);
  320. $gen_opnum{$name,$arity} = $op_num;
  321. $gen_arity{$name} = $arity;
  322. $gen_to_spec{"$name/$arity"} = undef;
  323. $num_specific{"$name/$arity"} = 0;
  324. $min_window{"$name/$arity"} = 255;
  325. }
  326. }
  327. #
  328. # Produce output for the chosen target.
  329. #
  330. &$target;
  331. #
  332. # Produce output needed by the emulator/loader.
  333. #
  334. sub emulator_output {
  335. my $i;
  336. my $name;
  337. my $key; # Loop variable.
  338. #
  339. # Information about opcodes (beam_opcodes.c).
  340. #
  341. $name = "$outdir/beam_opcodes.c";
  342. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  343. &comment('C');
  344. print "#ifdef HAVE_CONFIG_H\n";
  345. print "# include \"config.h\"\n";
  346. print "#endif\n\n";
  347. print '#include "sys.h"', "\n";
  348. print '#include "erl_vm.h"', "\n";
  349. print '#include "export.h"', "\n";
  350. print '#include "erl_process.h"', "\n";
  351. print '#include "bif.h"', "\n";
  352. print '#include "erl_atom_table.h"', "\n";
  353. print '#include "beam_load.h"', "\n";
  354. print "\n";
  355. print "char tag_to_letter[] = {\n ";
  356. for ($i = 0; $i < length($genop_types); $i++) {
  357. print "'$tag_type[$i]', ";
  358. }
  359. for (; $i < @tag_type; $i++) {
  360. print "'_', ";
  361. }
  362. print "\n};\n";
  363. print "\n";
  364. #
  365. # Generate code for specific ops.
  366. #
  367. my($spec_opnum) = 0;
  368. print "OpEntry opc[] = {\n";
  369. foreach $key (sort keys %specific_op) {
  370. $gen_to_spec{$key} = $spec_opnum;
  371. $num_specific{$key} = @{$specific_op{$key}};
  372. #
  373. # Pick up all instructions and manufacture sort keys; we must have
  374. # the most specific instructions appearing first (e.g. an 'x' operand
  375. # should be matched before 's' or 'd').
  376. #
  377. my(%items) = ();
  378. foreach (@{$specific_op{$key}}) {
  379. my($name, $hot, @args) = @{$_};
  380. my($sign) = join('', @args);
  381. # The primitive types should sort before other types.
  382. my($sort_key) = $sign;
  383. eval "\$sort_key =~ tr/$genop_types/./";
  384. $sort_key .= ":$sign";
  385. $items{$sort_key} = [$name, $hot, $sign, @args];
  386. }
  387. #
  388. # Now call the generator for the sorted result.
  389. #
  390. foreach (sort keys %items) {
  391. my($name, $hot, $sign, @args) = @{$items{$_}};
  392. my $arity = @args;
  393. my($instr) = "${name}_$sign";
  394. $instr =~ s/_$//;
  395. #
  396. # Call a generator to calculate size and generate macros
  397. # for the emulator.
  398. #
  399. my($size, $code, $pack) = &basic_generator($name, $hot, @args);
  400. #
  401. # Save the generated $code for later.
  402. #
  403. if (defined $code) {
  404. if ($hot) {
  405. push(@{$hot_code{$code}}, $instr);
  406. } else {
  407. push(@{$cold_code{$code}}, $instr);
  408. }
  409. }
  410. #
  411. # Calculate the bit mask which should be used to match this
  412. # instruction.
  413. #
  414. my(@bits) = (0) x ($max_spec_operands/2);
  415. my($i);
  416. for ($i = 0; $i < $max_spec_operands && defined $args[$i]; $i++) {
  417. my $t = $args[$i];
  418. if (defined $type_bit{$t}) {
  419. my $shift = $max_genop_types * ($i % 2);
  420. $bits[int($i/2)] |= $type_bit{$t} << $shift;
  421. }
  422. }
  423. printf "/* %3d */ ", $spec_opnum;
  424. my $print_name = $sign ne '' ? "${name}_$sign" : $name;
  425. my $init = "{";
  426. my $sep = "";
  427. foreach (@bits) {
  428. $init .= sprintf("%s0x%X", $sep, $_);
  429. $sep = ",";
  430. }
  431. $init .= "}";
  432. &init_item($print_name, $init, $size, $pack, $sign, 0);
  433. $op_to_name[$spec_opnum] = $instr;
  434. $spec_opnum++;
  435. }
  436. }
  437. print "};\n\n";
  438. print "int num_instructions = $spec_opnum;\n\n";
  439. #
  440. # Generate transformations.
  441. #
  442. &tr_gen(@transformations);
  443. #
  444. # Print the generic instruction table.
  445. #
  446. print "GenOpEntry gen_opc[] = {\n";
  447. for ($i = 0; $i < @gen_opname; $i++) {
  448. if ($i == $num_file_opcodes) {
  449. print "\n/*\n * Internal generic instructions.\n */\n\n";
  450. }
  451. my($name) = $gen_opname[$i];
  452. my($arity) = $gen_arity[$i];
  453. printf "/* %3d */ ", $i;
  454. if (!defined $name) {
  455. &init_item("", 0, 0, 0, -1);
  456. } else {
  457. my($key) = "$name/$arity";
  458. my($tr) = defined $gen_transform_offset{$key} ?
  459. $gen_transform_offset{$key} : -1;
  460. my($spec_op) = $gen_to_spec{$key};
  461. my($num_specific) = $num_specific{$key};
  462. defined $spec_op or
  463. $obsolete[$gen_opnum{$name,$arity}] or
  464. $is_transformed{$name,$arity} or
  465. error("instruction $key has no specific instruction");
  466. $spec_op = -1 unless defined $spec_op;
  467. &init_item($name, $arity, $spec_op, $num_specific, $tr, $min_window{$key});
  468. }
  469. }
  470. print "};\n";
  471. #
  472. # Information about opcodes (beam_opcodes.h).
  473. #
  474. $name = "$outdir/beam_opcodes.h";
  475. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  476. &comment('C');
  477. print "#ifndef __OPCODES_H__\n";
  478. print "#define __OPCODES_H__\n\n";
  479. print "#define BEAM_FORMAT_NUMBER $BEAM_FORMAT_NUMBER\n";
  480. print "#define MAX_GENERIC_OPCODE ", $num_file_opcodes-1, "\n";
  481. print "#define NUM_GENERIC_OPS ", scalar(@gen_opname), "\n";
  482. print "#define NUM_SPECIFIC_OPS ", scalar(@op_to_name), "\n";
  483. print "\n";
  484. print "#ifdef ARCH_64\n";
  485. print "# define BEAM_WIDE_MASK 0xFFFFUL\n";
  486. print "# define BEAM_LOOSE_MASK 0x1FFFUL\n";
  487. print "#if HALFWORD_HEAP\n";
  488. print "# define BEAM_TIGHT_MASK 0x1FFCUL\n";
  489. print "#else\n";
  490. print "# define BEAM_TIGHT_MASK 0x1FF8UL\n";
  491. print "#endif\n";
  492. print "# define BEAM_WIDE_SHIFT 32\n";
  493. print "# define BEAM_LOOSE_SHIFT 16\n";
  494. print "# define BEAM_TIGHT_SHIFT 16\n";
  495. print "#else\n";
  496. print "# define BEAM_LOOSE_MASK 0xFFF\n";
  497. print "# define BEAM_TIGHT_MASK 0xFFC\n";
  498. print "# define BEAM_LOOSE_SHIFT 16\n";
  499. print "# define BEAM_TIGHT_SHIFT 10\n";
  500. print "#endif\n";
  501. print "\n";
  502. #
  503. # Definitions of tags.
  504. #
  505. my $letter;
  506. my $tag_num = 0;
  507. &comment('C', "The following operand types for generic instructions",
  508. "occur in beam files.");
  509. foreach $letter (split('', $compiler_types)) {
  510. print "#define TAG_$letter $tag_num\n";
  511. $tag_num++;
  512. }
  513. print "\n";
  514. &comment('C', "The following operand types are only used in the loader.");
  515. foreach $letter (split('', $loader_types)) {
  516. print "#define TAG_$letter $tag_num\n";
  517. $tag_num++;
  518. }
  519. print "\n#define BEAM_NUM_TAGS $tag_num\n\n";
  520. $i = 0;
  521. foreach (sort keys %match_engine_ops) {
  522. print "#define $_ $i\n";
  523. $i++;
  524. }
  525. print "#define NUM_TOPS $i\n";
  526. print "\n";
  527. print "#define TE_MAX_VARS $te_max_vars\n";
  528. print "\n";
  529. print "extern char tag_to_letter[];\n";
  530. print "extern Uint op_transform[];\n";
  531. print "\n";
  532. for ($i = 0; $i < @op_to_name; $i++) {
  533. print "#define op_$op_to_name[$i] $i\n";
  534. }
  535. print "\n";
  536. print "#define NUMBER_OF_OPCODES ",scalar(@op_to_name),"\n";
  537. for ($i = 0; $i < @op_to_name; $i++) {
  538. print "#define op_count_$op_to_name[$i] ",$i+scalar(@op_to_name),"\n";
  539. }
  540. print "\n";
  541. print "#define DEFINE_OPCODES";
  542. foreach (@op_to_name) {
  543. print " \\\n&&lb_$_,";
  544. }
  545. print "\n\n";
  546. print "#define DEFINE_COUNTING_OPCODES";
  547. foreach (@op_to_name) {
  548. print " \\\n&&lb_count_$_,";
  549. }
  550. print "\n\n";
  551. print "#define DEFINE_COUNTING_LABELS";
  552. for ($i = 0; $i < @op_to_name; $i++) {
  553. my($name) = $op_to_name[$i];
  554. print " \\\nCountCase($name): opc[$i].count++; goto lb_$name;";
  555. }
  556. print "\n\n";
  557. for ($i = 0; $i < @gen_opname; $i++) {
  558. print "#define genop_$gen_opname[$i]_$gen_arity[$i] $i\n"
  559. if defined $gen_opname[$i];
  560. }
  561. print "#endif\n";
  562. #
  563. # Extension of transform engine.
  564. #
  565. $name = "$outdir/beam_tr_funcs.h";
  566. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  567. &comment('C');
  568. &tr_gen_call(@call_table);
  569. $name = "$outdir/beam_pred_funcs.h";
  570. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  571. &comment('C');
  572. &tr_gen_call(@pred_table);
  573. #
  574. # Implementation of operations for emulator.
  575. #
  576. $name = "$outdir/beam_hot.h";
  577. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  578. &comment('C');
  579. &print_code(\%hot_code);
  580. $name = "$outdir/beam_cold.h";
  581. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  582. &comment('C');
  583. &print_code(\%cold_code);
  584. }
  585. sub init_item {
  586. my($sep) = "";
  587. print "{";
  588. foreach (@_) {
  589. if (!defined $_) {
  590. print "${sep}NULL";
  591. } elsif (/^\{/) {
  592. print "$sep$_";
  593. } elsif (/^-?\d/) {
  594. print "$sep$_";
  595. } else {
  596. print "$sep\"$_\"";
  597. }
  598. $sep = ", ";
  599. }
  600. print "},\n";
  601. }
  602. sub q {
  603. my($str) = @_;
  604. "\"$str\"";
  605. }
  606. sub print_code {
  607. my($ref) = @_;
  608. my(%sorted);
  609. my($key, $label); # Loop variables.
  610. foreach $key (keys %$ref) {
  611. my($sort_key);
  612. my($code) = '';
  613. foreach $label (@{$ref->{$key}}) {
  614. $code .= "OpCase($label):\n";
  615. $sort_key = $label;
  616. }
  617. foreach (split("\n", $key)) {
  618. $code .= " $_\n";
  619. }
  620. $code .= "\n";
  621. $sorted{$sort_key} = $code;
  622. }
  623. foreach (sort keys %sorted) {
  624. print $sorted{$_};
  625. }
  626. }
  627. #
  628. # Produce output needed by the compiler back-end (assembler).
  629. #
  630. sub compiler_output {
  631. my($module) = 'beam_opcodes';
  632. my($name) = "${module}.erl";
  633. my($i);
  634. open(STDOUT, ">$outdir/$name") || die "Failed to open $name for writing: $!\n";
  635. print "-module($module).\n";
  636. &comment('erlang');
  637. print "-export([format_number/0]).\n";
  638. print "-export([opcode/2,opname/1]).\n";
  639. print "\n";
  640. print "-spec format_number() -> $BEAM_FORMAT_NUMBER.\n";
  641. print "format_number() -> $BEAM_FORMAT_NUMBER.\n\n";
  642. print "-spec opcode(atom(), 0..", $max_gen_operands, ") -> 1..", $num_file_opcodes-1, ".\n";
  643. for ($i = 0; $i < @gen_opname; $i++) {
  644. next unless defined $gen_opname[$i];
  645. print "%%" if $obsolete[$i];
  646. print "opcode(", &quote($gen_opname[$i]), ", $gen_arity[$i]) -> $i;\n";
  647. }
  648. print "opcode(Name, Arity) -> erlang:error(badarg, [Name,Arity]).\n\n";
  649. print "-spec opname(1..", $num_file_opcodes-1, ") -> {atom(),0..", $max_gen_operands, "}.\n";
  650. for ($i = 0; $i < @gen_opname; $i++) {
  651. next unless defined $gen_opname[$i];
  652. print "opname($i) -> {",
  653. &quote($gen_opname[$i]), ",$gen_arity[$i]};\n";
  654. }
  655. print "opname(Number) -> erlang:error(badarg, [Number]).\n";
  656. #
  657. # Generate .hrl file.
  658. #
  659. my($name) = "$outdir/${module}.hrl";
  660. open(STDOUT, ">$name") || die "Failed to open $name for writing: $!\n";
  661. &comment('erlang');
  662. for ($i = 0; $i < @tag_type && $i < 8; $i++) {
  663. print "-define(tag_$tag_type[$i], $i).\n";
  664. }
  665. print "\n";
  666. }
  667. #
  668. # Check an operation for validity.
  669. #
  670. sub syntax_check {
  671. my($name, @args) = @_;
  672. my($i);
  673. &error("Bad opcode name '$name'")
  674. unless $name =~ /^[a-z][\w\d_]*$/;
  675. for ($i = 0; $i < @args; $i++) {
  676. &error("Argument " . ($i+1) . ": invalid type '$args[$i]'")
  677. unless defined $arg_size{$args[$i]};
  678. }
  679. }
  680. sub error {
  681. my(@message) = @_;
  682. my($where) = $. ? "$ARGV($.): " : "";
  683. die $where, @message, "\n";
  684. }
  685. sub sanity {
  686. die "internal error: ", @_, "\n";
  687. }
  688. sub comment {
  689. my($lang, @comments) = @_;
  690. my($prefix);
  691. if ($lang eq 'C') {
  692. print "/*\n";
  693. $prefix = " * ";
  694. } elsif ($lang eq 'erlang') {
  695. $prefix = '%% ';
  696. } else {
  697. $prefix = '# ';
  698. }
  699. my(@prog) = split('/', $0);
  700. my($prog) = $prog[$#prog];
  701. if (@comments) {
  702. my $line;
  703. foreach $line (@comments) {
  704. print "$prefix$line\n";
  705. }
  706. } else {
  707. print "$prefix Warning: Do not edit this file.\n";
  708. print "$prefix Auto-generated by '$prog'.\n";
  709. }
  710. if ($lang eq 'C') {
  711. print " */\n";
  712. }
  713. print "\n";
  714. }
  715. #
  716. # Basic implementation of instruction in emulator loop
  717. # (assuming no packing).
  718. #
  719. sub basic_generator {
  720. my($name, $hot, @args) = @_;
  721. my($size) = 0;
  722. my($macro) = '';
  723. my($flags) = '';
  724. my(@f);
  725. my(@f_types);
  726. my($fail_type);
  727. my($prefix) = '';
  728. my($tmp_arg_num) = 1;
  729. my($pack_spec) = '';
  730. my($var_decls) = '';
  731. my($gen_dest_arg) = 'StoreSimpleDest';
  732. my($i);
  733. # The following argument types should be included as macro arguments.
  734. my(%incl_arg) = ('c' => 1,
  735. 'i' => 1,
  736. 'a' => 1,
  737. 'A' => 1,
  738. 'N' => 1,
  739. 'U' => 1,
  740. 'I' => 1,
  741. 't' => 1,
  742. 'P' => 1,
  743. 'Q' => 1,
  744. );
  745. # Pick up the macro to use and its flags (if any).
  746. $macro = $macro{$name} if defined $macro{$name};
  747. $flags = $macro_flags{$name} if defined $macro_flags{$name};
  748. #
  749. # Add any arguments to be included as macro arguments (for instance,
  750. # 'p' is usually not an argument, except for calls).
  751. #
  752. while ($flags =~ /-arg_(\w)/g) {
  753. $incl_arg{$1} = 1;
  754. };
  755. #
  756. # Pack arguments if requested.
  757. #
  758. if ($flags =~ /-pack/ && $hot) {
  759. ($prefix, $pack_spec, @args) = &do_pack(@args);
  760. }
  761. #
  762. # Calculate the size of the instruction and generate each argument for
  763. # the macro.
  764. #
  765. foreach (@args) {
  766. my($this_size) = $arg_size{$_};
  767. SWITCH:
  768. {
  769. /^pack:(\d):(.*)/ and do { push(@f, $2);
  770. push(@f_types, 'packed');
  771. $this_size = $1;
  772. last SWITCH;
  773. };
  774. /r/ and do { push(@f, "r(0)"); push(@f_types, $_); last SWITCH };
  775. /[xy]/ and do { push(@f, "$_" . "b(Arg($size))");
  776. push(@f_types, $_);
  777. last SWITCH;
  778. };
  779. /n/ and do { push(@f, "NIL"); push(@f_types, $_); last SWITCH };
  780. /s/ and do { my($tmp) = "targ$tmp_arg_num";
  781. $var_decls .= "Eterm $tmp; ";
  782. $tmp_arg_num++;
  783. push(@f, $tmp);
  784. push(@f_types, $_);
  785. $prefix .= "GetR($size, $tmp);\n";
  786. last SWITCH; };
  787. /d/ and do { $var_decls .= "Eterm dst; ";
  788. push(@f, "dst");
  789. push(@f_types, $_);
  790. $prefix .= "dst = Arg($size);\n";
  791. $gen_dest_arg = 'StoreResult';
  792. last SWITCH;
  793. };
  794. defined($incl_arg{$_})
  795. and do { push(@f, "Arg($size)");
  796. push(@f_types, $_);
  797. last SWITCH;
  798. };
  799. /[fp]/ and do { $fail_type = $_; last SWITCH };
  800. /[eLIFEbASjPowlq]/ and do { last SWITCH; };
  801. die "$name: The generator can't handle $_, at";
  802. }
  803. $size += $this_size;
  804. }
  805. #
  806. # If requested, pass a pointer to the destination register.
  807. # The destination must be the last operand.
  808. #
  809. if ($flags =~ /-gen_dest/) {
  810. push(@f, $gen_dest_arg);
  811. }
  812. #
  813. # Add a fail action macro if requested.
  814. #
  815. $flags =~ /-fail_action/ and do {
  816. if (!defined $fail_type) {
  817. my($i);
  818. for ($i = 0; $i < @f_types; $i++) {
  819. local($_) = $f_types[$i];
  820. /[rxycians]/ and do { push(@f, "Badmatch($f[$i])"); next };
  821. }
  822. } elsif ($fail_type eq 'f') {
  823. push(@f, "ClauseFail()");
  824. } else {
  825. my($i);
  826. for ($i = 0; $i < @f_types; $i++) {
  827. local($_) = $f_types[$i];
  828. /[rxycians]/ and do { push(@f, "Badmatch($f[$i])"); next };
  829. }
  830. }
  831. };
  832. #
  833. # Add a size argument if requested.
  834. #
  835. $flags =~ /-size/ and do {
  836. push(@f, $size);
  837. };
  838. # Generate the macro if requested.
  839. my($code);
  840. if (defined $macro{$name}) {
  841. my($macro_code) = "$prefix$macro(" . join(', ', @f) . ");";
  842. $var_decls .= "BeamInstr tmp_packed1;"
  843. if $macro_code =~ /tmp_packed1/;
  844. $var_decls .= "BeamInstr tmp_packed2;"
  845. if $macro_code =~ /tmp_packed2/;
  846. if ($flags =~ /-nonext/) {
  847. $code = join("\n",
  848. "{ $var_decls",
  849. $macro_code,
  850. "}");
  851. } elsif ($flags =~ /-goto:(\S*)/) {
  852. my $goto = $1;
  853. $code = join("\n",
  854. "{ $var_decls",
  855. $macro_code,
  856. "I += $size + 1;",
  857. "goto $goto;",
  858. "}");
  859. } else {
  860. $code = join("\n",
  861. "{ $var_decls",
  862. "BeamInstr* next;",
  863. "PreFetch($size, next);",
  864. "$macro_code",
  865. "NextPF($size, next);",
  866. "}", "");
  867. }
  868. }
  869. # Return the size and code for the macro (if any).
  870. $size++;
  871. ($size, $code, $pack_spec);
  872. }
  873. sub do_pack {
  874. my(@args) = @_;
  875. my($packable_args) = 0;
  876. my @is_packable; # Packability (boolean) for each argument.
  877. my $wide_packing = 0;
  878. #
  879. # Count the number of packable arguments. If we encounter any 's' or 'd'
  880. # arguments, packing is not possible.
  881. #
  882. my $packable_types = "xytQ";
  883. foreach my $arg (@args) {
  884. if ($arg =~ /^[$packable_types]/) {
  885. $packable_args++;
  886. push @is_packable, 1;
  887. } elsif ($arg =~ /^I/ and $wordsize == 64 and $packable_args < 2) {
  888. $wide_packing = 1;
  889. push @is_packable, 1;
  890. if (++$packable_args == 2) {
  891. # We can only pack two arguments. Turn off packing
  892. # for the rest of the arguments.
  893. $packable_types = "\xFF";
  894. }
  895. } elsif ($arg =~ /^[sd]/) {
  896. return ('', '', @args);
  897. } else {
  898. push @is_packable, 0;
  899. }
  900. }
  901. #
  902. # Get out of here if too few or too many arguments.
  903. #
  904. return ('', '', @args) if $packable_args < 2;
  905. &error("too many packable arguments") if $packable_args > 4;
  906. my($size) = 0;
  907. my($pack_prefix) = '';
  908. my($down) = ''; # Pack commands (towards instruction
  909. # beginning).
  910. my($up) = ''; # Pack commands (storing back while
  911. # moving forward).
  912. my $args_per_word;
  913. if ($packable_args < 4 or $wordsize == 64) {
  914. $args_per_word = $packable_args;
  915. } else {
  916. # 4 packable argument, 32 bit wordsize. Need 2 words.
  917. $args_per_word = 2;
  918. }
  919. my @shift;
  920. my @mask;
  921. my @instr;
  922. if ($wide_packing) {
  923. @shift = ('0', 'BEAM_WIDE_SHIFT');
  924. @mask = ('BEAM_WIDE_MASK', $WHOLE_WORD);
  925. @instr = ('w', 'i');
  926. } else {
  927. @shift = @{$pack_shift[$args_per_word]};
  928. @mask = @{$pack_mask[$args_per_word]};
  929. @instr = @{$pack_instr[$args_per_word]};
  930. }
  931. #
  932. # Now generate the packing instructions. One complication is that
  933. # the packing engine works from right-to-left, but we must generate
  934. # the instructions from left-to-right because we must calculate
  935. # instruction sizes from left-to-right.
  936. #
  937. # XXX Packing 3 't's in one word won't work. Sorry.
  938. my $did_some_packing = 0; # Nothing packed yet.
  939. my($ap) = 0; # Argument number within word.
  940. my($tmpnum) = 1; # Number of temporary variable.
  941. my($expr) = '';
  942. for (my $i = 0; $i < @args; $i++) {
  943. my($reg) = $args[$i];
  944. my($this_size) = $arg_size{$reg};
  945. if ($is_packable[$i]) {
  946. $this_size = 0;
  947. $did_some_packing = 1;
  948. if ($ap == 0) {
  949. $pack_prefix .= "tmp_packed$tmpnum = Arg($size);\n";
  950. $up .= "p";
  951. $down = "P$down";
  952. $this_size = 1;
  953. }
  954. $down = "$instr[$ap]$down";
  955. my($unpack) = &make_unpack($tmpnum, $shift[$ap], $mask[$ap]);
  956. $args[$i] = "pack:$this_size:$reg" . "b($unpack)";
  957. if (++$ap == $args_per_word) {
  958. $ap = 0;
  959. $tmpnum++;
  960. }
  961. } elsif ($arg_size{$reg} && $did_some_packing) {
  962. #
  963. # This is an argument that can't be packed. Normally, we must
  964. # save it on the pack engine's stack, unless:
  965. #
  966. # 1. The argument has zero size (e.g. r(0)). Such arguments
  967. # will not be loaded. They disappear.
  968. # 2. If the argument is on the left of the first packed argument,
  969. # the packing engine will never access it (because the engine
  970. # operates from right-to-left).
  971. #
  972. $down = "g${down}";
  973. $up = "${up}p";
  974. }
  975. $size += $this_size;
  976. }
  977. my $pack_spec = $down . $up;
  978. return ($pack_prefix, $pack_spec, @args);
  979. }
  980. sub make_unpack {
  981. my($tmpnum, $shift, $mask) = @_;
  982. my($e) = "tmp_packed$tmpnum";
  983. $e = "($e>>$shift)" if $shift;
  984. $e .= "&$mask" unless $mask eq $WHOLE_WORD;
  985. $e;
  986. }
  987. sub quote {
  988. local($_) = @_;
  989. return "'$_'" if $_ eq 'try';
  990. return "'$_'" if $_ eq 'catch';
  991. return "'$_'" if $_ eq 'receive';
  992. return "'$_'" if $_ =~ /^[A-Z]/;
  993. $_;
  994. }
  995. #
  996. # Parse instruction transformations when they first appear.
  997. #
  998. sub parse_transformation {
  999. local($_) = @_;
  1000. my($orig) = $_;
  1001. my($from, $to) = split(/\s*=>\s*/);
  1002. my(@op);
  1003. # The source instructions.
  1004. my(@from) = split(/\s*\|\s*/, $from);
  1005. foreach (@from) {
  1006. if (/^(\w+)\((.*?)\)/) {
  1007. my($name, $arglist) = ($1, $2);
  1008. $_ = (&compile_transform_function($name, split(/\s*,\s*/, $arglist)));
  1009. } else {
  1010. (@op) = split;
  1011. $_ = &compile_transform(1, @op);
  1012. }
  1013. }
  1014. #
  1015. # Check for a function which should be called to provide the new
  1016. # instructions if the left-hand side matched. Otherwise there is
  1017. # an explicit list of instructions.
  1018. #
  1019. my @to;
  1020. if ($to =~ /^(\w+)\((.*?)\)/) {
  1021. my($name, $arglist) = ($1, $2);
  1022. @to = (&compile_transform_function($name, split(/\s*,\s*/, $arglist)));
  1023. } else {
  1024. @to = split(/\s*\|\s*/, $to);
  1025. foreach (@to) {
  1026. (@op) = split;
  1027. $_ = &compile_transform(0, @op);
  1028. }
  1029. }
  1030. push(@transformations, [$., $orig, [@from], [reverse @to]]);
  1031. }
  1032. sub compile_transform_function {
  1033. my($name, @args) = @_;
  1034. [".$name", 0, @args];
  1035. }
  1036. sub compile_transform {
  1037. my($src, $name, @ops) = @_;
  1038. my $arity = 0;
  1039. foreach (@ops) {
  1040. my(@list) = &tr_parse_op($src, $_);
  1041. $arity++ unless $list[1] eq '*';
  1042. $_ = [ @list ];
  1043. }
  1044. if ($obsolete[$gen_opnum{$name,$arity}]) {
  1045. error("obsolete function must not be used in transformations");
  1046. }
  1047. if ($src) {
  1048. $is_transformed{$name,$arity} = 1;
  1049. }
  1050. [$name,$arity,@ops];
  1051. }
  1052. sub tr_parse_op {
  1053. my($src, $op) = @_;
  1054. my($var) = '';
  1055. my($type) = '';
  1056. my($type_val) = 0;
  1057. my($cond) = '';
  1058. my($cond_val) = '';
  1059. local($_) = $op;
  1060. # Get the variable name if any.
  1061. if (/^([A-Z]\w*)(.*)/) {
  1062. $var = $1;
  1063. $_ = $2;
  1064. &error("garbage after variable")
  1065. unless /^=(.*)/ or /^(\s*)$/;
  1066. $_ = $1;
  1067. }
  1068. # Get the type if any.
  1069. if (/^([a-z*]+)(.*)/) {
  1070. $type = $1;
  1071. $_ = $2;
  1072. foreach (split('', $type)) {
  1073. &error("bad type in $op")
  1074. unless defined $type_bit{$_} or $type eq '*';
  1075. }
  1076. }
  1077. # Get an optional condition. (In source.)
  1078. if (/^==(.*)/) {
  1079. $cond = 'is_eq';
  1080. $cond_val = $1;
  1081. $_ = '';
  1082. } elsif (/^\$is_bif(.*)/) {
  1083. $cond = 'is_bif';
  1084. $cond_val = -1;
  1085. $_ = $1;
  1086. } elsif (/^\$is_not_bif(.*)/) {
  1087. $cond = 'is_not_bif';
  1088. $cond_val = -1;
  1089. $_ = $1;
  1090. } elsif (m@^\$bif:(\w+):(\w+)/(\d)(.*)@) {
  1091. $cond = 'is_bif';
  1092. if ($1 eq 'erlang') {
  1093. $cond_val = "BIF_$2_$3";
  1094. } else {
  1095. $cond_val = "BIF_$1_$2_$3";
  1096. }
  1097. $_ = $4;
  1098. } elsif (m@^\$func:(\w+):(\w+)/([_\d])(.*)@) {
  1099. my $arity = $3 eq '_' ? 1024 : $3;
  1100. $cond = 'is_func';
  1101. $cond_val = "$1:$2:$arity";
  1102. $_ = $4;
  1103. }
  1104. # Get an optional value. (In destination.)
  1105. if (/^=(.*)/) {
  1106. $type_val = $1;
  1107. $_ = '';
  1108. }
  1109. # Nothing more is allowed after the command.
  1110. &error("garbage '$_' after operand: $op")
  1111. unless /^\s*$/;
  1112. # Test that destination has no conditions.
  1113. unless ($src) {
  1114. error("condition not allowed in destination: $op")
  1115. if $cond;
  1116. error("variable name and type cannot be combined in destination: $op")
  1117. if $var && $type;
  1118. }
  1119. # Test that source has no values.
  1120. if ($src) {
  1121. error("value not allowed in source: $op")
  1122. if $type_val;
  1123. }
  1124. ($var,$type,$type_val,$cond,$cond_val);
  1125. }
  1126. #
  1127. # Generate code for all transformations.
  1128. #
  1129. sub tr_gen {
  1130. my(@g) = @_;
  1131. my($ref, $key, $instr); # Loop variables.
  1132. foreach $ref (@g) {
  1133. my($line, $orig_transform, $from_ref, $to_ref) = @$ref;
  1134. my $used_ref = used_vars($from_ref, $to_ref);
  1135. my $so_far = tr_gen_from($line, $used_ref, @$from_ref);
  1136. tr_gen_to($line, $orig_transform, $so_far, @$to_ref);
  1137. }
  1138. #
  1139. # Print the generated transformation engine.
  1140. #
  1141. my($offset) = 0;
  1142. print "Uint op_transform[] = {\n";
  1143. foreach $key (sort keys %gen_transform) {
  1144. $gen_transform_offset{$key} = $offset;
  1145. my @instr = @{$gen_transform{$key}};
  1146. #
  1147. # If the last instruction is 'fail', remove it and
  1148. # convert the previous 'try_me_else' to 'try_me_else_fail'.
  1149. #
  1150. if (is_instr($instr[$#instr], 'fail')) {
  1151. pop(@instr);
  1152. my $i = $#instr;
  1153. $i-- while !is_instr($instr[$i], 'try_me_else');
  1154. $instr[$i] = make_op('', 'try_me_else_fail');
  1155. }
  1156. foreach $instr (@instr) {
  1157. my($size, $instr_ref, $comment) = @$instr;
  1158. my($op, @args) = @$instr_ref;
  1159. print " ";
  1160. if (!defined $op) {
  1161. $comment =~ s/\n(.)/\n $1/g;
  1162. print "\n", $comment;
  1163. } else {
  1164. $op = "TOP_$op";
  1165. $match_engine_ops{$op} = 1;
  1166. if ($comment ne '') {
  1167. printf "%-24s /* %s */\n", (join(", ", ($op, @args)) . ","),
  1168. $comment;
  1169. } else {
  1170. print join(", ", ($op, @args)), ",\n";
  1171. }
  1172. $offset += $size;
  1173. }
  1174. }
  1175. print "\n";
  1176. }
  1177. print "/*\n";
  1178. print " * Total number of words: $offset\n";
  1179. print " */\n";
  1180. print "};\n\n";
  1181. }
  1182. sub used_vars {
  1183. my($from_ref,$to_ref) = @_;
  1184. my %used;
  1185. my %seen;
  1186. foreach my $ref (@$from_ref) {
  1187. my($name,$arity,@ops) = @$ref;
  1188. if ($name =~ /^[.]/) {
  1189. foreach my $var (@ops) {
  1190. $used{$var} = 1;
  1191. }
  1192. } else {
  1193. # Any variable that is used at least twice on the
  1194. # left-hand side is used. (E.g. "move R R".)
  1195. foreach my $op (@ops) {
  1196. my($var, $type, $type_val) = @$op;
  1197. next if $var eq '';
  1198. $used{$var} = 1 if $seen{$var};
  1199. $seen{$var} = 1;
  1200. }
  1201. }
  1202. }
  1203. foreach my $ref (@$to_ref) {
  1204. my($name, $arity, @ops) = @$ref;
  1205. if ($name =~ /^[.]/) {
  1206. foreach my $var (@ops) {
  1207. $used{$var} = 1;
  1208. }
  1209. } else {
  1210. foreach my $op (@ops) {
  1211. my($var, $type, $type_val) = @$op;
  1212. next if $var eq '';
  1213. $used{$var} = 1;
  1214. }
  1215. }
  1216. }
  1217. \%used;
  1218. }
  1219. sub tr_gen_from {
  1220. my($line,$used_ref,@tr) = @_;
  1221. my(%var) = ();
  1222. my(%var_type);
  1223. my($var_num) = 0;
  1224. my(@code);
  1225. my($min_window) = 0;
  1226. my(@fix_rest_args);
  1227. my(@fix_pred_funcs);
  1228. my($op, $ref); # Loop variables.
  1229. my $where = "left side of transformation in line $line: ";
  1230. my %var_used = %$used_ref;
  1231. my $may_fail = 0;
  1232. my $is_first = 1;
  1233. foreach $ref (@tr) {
  1234. my($name, $arity, @ops) = @$ref;
  1235. my($key) = "$name/$arity";
  1236. my($opnum);
  1237. $may_fail = 1 unless $is_first;
  1238. $is_first = 0;
  1239. #
  1240. # A name starting with a period is a C pred function to be called.
  1241. #
  1242. if ($name =~ /^\.(\w+)/) {
  1243. $name = $1;
  1244. $may_fail = 1;
  1245. my $var;
  1246. my(@args);
  1247. push(@fix_pred_funcs, scalar(@code));
  1248. push(@code, [$name, @ops]);
  1249. next;
  1250. }
  1251. #
  1252. # Check that $name/$arity refers to a valid generic instruction.
  1253. #
  1254. &error($where, "invalid generic op $name/$arity")
  1255. unless defined $gen_opnum{$name,$arity};
  1256. $opnum = $gen_opnum{$name,$arity};
  1257. push(@code, make_op("$name/$arity", 'next_instr', $opnum));
  1258. $min_window++;
  1259. foreach $op (@ops) {
  1260. my($var, $type, $type_val, $cond, $val) = @$op;
  1261. my $ignored_var = "$var (ignored)";
  1262. if ($type ne '' && $type ne '*') {
  1263. $may_fail = 1;
  1264. #
  1265. # The is_bif, is_not_bif, and is_func instructions have
  1266. # their own built-in type test and don't need to
  1267. # be guarded with a type test instruction.
  1268. #
  1269. $ignored_var = '';
  1270. unless ($cond eq 'is_bif' or
  1271. $cond eq 'is_not_bif' or
  1272. $cond eq 'is_func') {
  1273. my($types) = '';
  1274. my($type_mask) = 0;
  1275. foreach (split('', $type)) {
  1276. $types .= "$_ ";
  1277. $type_mask |= $type_bit{$_};
  1278. }
  1279. if ($cond ne 'is_eq') {
  1280. push(@code, &make_op($types, 'is_type', $type_mask));
  1281. } else {
  1282. $cond = '';
  1283. push(@code, &make_op("$types== $val", 'is_type_eq',
  1284. $type_mask, $val));
  1285. }
  1286. }
  1287. }
  1288. if ($cond eq 'is_func') {
  1289. my($m, $f, $a) = split(/:/, $val);
  1290. $ignored_var = '';
  1291. $may_fail = 1;
  1292. push(@code, &make_op('', "$cond", "am_$m",
  1293. "am_$f", $a));
  1294. } elsif ($cond ne '') {
  1295. $ignored_var = '';
  1296. $may_fail = 1;
  1297. push(@code, &make_op('', "$cond", $val));
  1298. }
  1299. if ($var ne '') {
  1300. if (defined $var{$var}) {
  1301. $ignored_var = '';
  1302. $may_fail = 1;
  1303. push(@code, &make_op($var, 'is_same_var', $var{$var}));
  1304. } elsif ($type eq '*') {
  1305. #
  1306. # Reserve a hole for a 'rest_args' instruction.
  1307. #
  1308. $ignored_var = '';
  1309. push(@fix_rest_args, scalar(@code));
  1310. push(@code, $var);
  1311. } elsif ($var_used{$var}) {
  1312. $ignored_var = '';
  1313. $var_type{$var} = 'scalar';
  1314. $var{$var} = $var_num;
  1315. $var_num++;
  1316. push(@code, &make_op($var, 'set_var', $var{$var}));
  1317. }
  1318. }
  1319. if (is_instr($code[$#code], 'set_var')) {
  1320. my $ref = pop @code;
  1321. my $comment = $ref->[2];
  1322. my $var = $ref->[1][1];
  1323. push(@code, make_op($comment, 'set_var_next_arg', $var));
  1324. } else {
  1325. push(@code, &make_op($ignored_var, 'next_arg'));
  1326. }
  1327. }
  1328. # Remove redundant 'next_arg' instructions before the end
  1329. # of the instruction.
  1330. pop(@code) while is_instr($code[$#code], 'next_arg');
  1331. }
  1332. #
  1333. # Insert the commit operation.
  1334. #
  1335. push(@code, make_op($may_fail ? '' : 'always reached', 'commit'));
  1336. #
  1337. # If there is an rest_args instruction, we must insert its correct
  1338. # variable number (higher than any other).
  1339. #
  1340. my $index;
  1341. &error("only one use of a '*' variable is allowed on the left hand side of a transformation")
  1342. if @fix_rest_args > 1;
  1343. foreach $index (@fix_rest_args) {
  1344. my $var = $code[$index];
  1345. $var{$var} = $var_num++;
  1346. $var_type{$var} = 'array';
  1347. splice(@code, $index, 1, &make_op($var, 'rest_args', $var{$var}));
  1348. }
  1349. foreach $index (@fix_pred_funcs) {
  1350. my($name, @ops) = @{$code[$index]};
  1351. my(@args);
  1352. my $var;
  1353. foreach $var (@ops) {
  1354. &error($where, "variable '$var' unbound")
  1355. unless defined $var{$var};
  1356. if ($var_type{$var} eq 'scalar') {
  1357. push(@args, "var[$var{$var}]");
  1358. } else {
  1359. push(@args, "var+$var{$var}");
  1360. }
  1361. }
  1362. my $pi = tr_next_index(\@pred_table, \%pred_table, $name, @args);
  1363. splice(@code, $index, 1, make_op("$name()", 'pred', $pi));
  1364. }
  1365. $te_max_vars = $var_num
  1366. if $te_max_vars < $var_num;
  1367. [$min_window, \%var, \%var_type, \@code];
  1368. }
  1369. sub tr_gen_to {
  1370. my($line, $orig_transform, $so_far, @tr) = @_;
  1371. my($min_window, $var_ref, $var_type_ref, $code_ref) = @$so_far;
  1372. my(%var) = %$var_ref;
  1373. my(%var_type) = %$var_type_ref;
  1374. my(@code) = @$code_ref;
  1375. my($op, $ref); # Loop variables.
  1376. my($where) = "right side of transformation in line $line: ";
  1377. my $last_instr = $code[$#code];
  1378. my $cannot_fail = is_instr($last_instr, 'commit') &&
  1379. (get_comment($last_instr) =~ /^always/);
  1380. foreach $ref (@tr) {
  1381. my($name, $arity, @ops) = @$ref;
  1382. #
  1383. # A name starting with a period is a C function to be called.
  1384. #
  1385. if ($name =~ /^\.(\w+)/) {
  1386. $name = $1;
  1387. my $var;
  1388. my(@args);
  1389. foreach $var (@ops) {
  1390. &error($where, "variable '$var' unbound")
  1391. unless defined $var{$var};
  1392. if ($var_type{$var} eq 'scalar') {
  1393. push(@args, "var[$var{$var}]");
  1394. } else {
  1395. push(@args, "var+$var{$var}");
  1396. }
  1397. }
  1398. pop(@code); # Get rid of 'commit' instruction
  1399. my $index = tr_next_index(\@call_table, \%call_table,
  1400. $name, @args);
  1401. push(@code, make_op("$name()", 'call_end', $index));
  1402. last;
  1403. }
  1404. #
  1405. # Check that $name/$arity refers to a valid generic instruction.
  1406. #
  1407. my($key) = "$name/$arity";
  1408. &error($where, "invalid generic op $name/$arity")
  1409. unless defined $gen_opnum{$name,$arity};
  1410. my $opnum = $gen_opnum{$name,$arity};
  1411. #
  1412. # Create code to build the generic instruction.
  1413. #
  1414. push(@code, make_op("$name/$arity", 'new_instr', $opnum));
  1415. foreach $op (@ops) {
  1416. my($var, $type, $type_val) = @$op;
  1417. if ($var ne '') {
  1418. &error($where, "variable '$var' unbound")
  1419. unless defined $var{$var};
  1420. push(@code, &make_op($var, 'store_var_next_arg', $var{$var}));
  1421. } elsif ($type ne '') {
  1422. push(@code, &make_op('', 'store_type', "TAG_$type"));
  1423. if ($type_val) {
  1424. push(@code, &make_op('', 'store_val', $type_val));
  1425. }
  1426. push(@code, make_op('', 'next_arg'));
  1427. }
  1428. }
  1429. pop(@code) if is_instr($code[$#code], 'next_arg');
  1430. }
  1431. push(@code, make_op('', 'end'))
  1432. unless is_instr($code[$#code], 'call_end');
  1433. #
  1434. # Chain together all codes segments having the same first operation.
  1435. #
  1436. my($first_ref) = shift(@code);
  1437. my($size, $first, $key) = @$first_ref;
  1438. my($dummy, $op, $arity) = @$first;
  1439. my($comment) = "\n/*\n * Line $line:\n * $orig_transform\n */\n\n";
  1440. $min_window{$key} = $min_window
  1441. if $min_window{$key} > $min_window;
  1442. my $prev_last;
  1443. $prev_last = pop(@{$gen_transform{$key}})
  1444. if defined @{$gen_transform{$key}}; # Fail
  1445. if ($prev_last && !is_instr($prev_last, 'fail')) {
  1446. error("Line $line: A previous transformation shadows '$orig_transform'");
  1447. }
  1448. unless ($cannot_fail) {
  1449. unshift(@code, make_op('', 'try_me_else',
  1450. tr_code_len(@code)));
  1451. push(@code, make_op(""), make_op("$key", 'fail'));
  1452. }
  1453. unshift(@code, make_op($comment));
  1454. push(@{$gen_transform{$key}}, @code),
  1455. }
  1456. sub tr_code_len {
  1457. my($sum) = 0;
  1458. my($ref);
  1459. foreach $ref (@_) {
  1460. $sum += $$ref[0];
  1461. }
  1462. $sum;
  1463. }
  1464. sub make_op {
  1465. my($comment, @op) = @_;
  1466. [scalar(@op), [@op], $comment];
  1467. }
  1468. sub is_instr {
  1469. my($ref,$op) = @_;
  1470. return 0 unless ref($ref) eq 'ARRAY';
  1471. $ref->[1][0] eq $op;
  1472. }
  1473. sub get_comment {
  1474. my($ref,$op) = @_;
  1475. return '' unless ref($ref) eq 'ARRAY';
  1476. $ref->[2];
  1477. }
  1478. sub tr_next_index {
  1479. my($lref,$href,$name,@args) = @_;
  1480. my $code = "RVAL = $name(" . join(', ', 'st', @args) . "); break;\n";
  1481. my $index;
  1482. if (defined $$href{$code}) {
  1483. $index = $$href{$code};
  1484. } else {
  1485. $index = scalar(@$lref);
  1486. push(@$lref, $code);
  1487. $$href{$code} = $index;
  1488. }
  1489. $index;
  1490. }
  1491. sub tr_gen_call {
  1492. my(@call_table) = @_;
  1493. my($i);
  1494. for ($i = 0; $i < @call_table; $i++) {
  1495. print "case $i: $call_table[$i]";
  1496. }
  1497. }