reject programs that export symbols after they have been used
[voodoo-lang.git] / lib / voodoo / generators / arm_gas_generator.rb
blobceb381297b9d7b7286e29a6d4a45c29518ba64f5
1 require 'voodoo/generators/common_code_generator'
2 require 'set'
4 module Voodoo
5   # = ARM GNU Assembler Code Generator
6   #
7   # The ARM code generator generates assembly code for use with
8   # the GNU assembler.
9   #
10   # == Calling Convention
11   #
12   # The first four arguments are passed in the registers r0 through r3.
13   # Any additional arguments are passed on the stack, starting at
14   # r13. r13 will always be a multiple of 8.
15   #
16   # The return address for the called function is passed in r14.
17   #
18   # The called function will store its return value in r0.
19   #
20   # The called function is required to preserve the values of registers
21   # r4 through r11 and register r13.
22   #
23   # This calling convention is compatible with the Procedure Call
24   # Standard for the ARM Architecture (AAPCS).
25   #
26   # == Call Frames
27   #
28   # Call frames have the following layout:
29   #
30   # When a function is called, it receives a stack frame that looks like
31   # the following:
32   #
33   #   :
34   #   old frame
35   #   padding
36   #   argn
37   #   :
38   #   arg4        <-- r13 points here
39   #
40   # The function prologue of functions generated by this code generator
41   # creates activation frames that look as follows:
42   #
43   #   :
44   #   old frame
45   #   padding
46   #   argn
47   #   :
48   #   arg4       <-- r11 points here
49   #   saved r14
50   #   saved r11
51   #   :
52   #   saved r4
53   #   local6
54   #   :
55   #   localn     <-- r13 points here
56   #
57   # == Register Usage
58   #
59   # Inside a function, registers r4..r8 and r10 are used for local variables
60   # and function arguments, whereas r11 is used as a frame pointer.
61   #
62   # r12 is used as a temporary, and r3, r2 and r1 are used when more
63   # temporaries are needed.
64   #
65   # == Local Variables
66   #
67   # Local variables are used to store both the first 4 function arguments
68   # and any variables declared inside the function (arguments beyond the 4th
69   # are stored on the stack, as per the calling convention). Local variables
70   # beyond the 6th are stored on the stack, starting below the saved registers
71   # and counting down.
72   #
73   class ARMGasGenerator < CommonCodeGenerator
74     def initialize params
75       @WORDSIZE_BITS = 2
76       @WORDSIZE = 1 << @WORDSIZE_BITS
77       @CODE_ALIGNMENT = 4
78       @DATA_ALIGNMENT = @WORDSIZE
79       @FUNCTION_ALIGNMENT = @WORDSIZE
80       @STACK_ALIGNMENT_BITS = 3
81       @STACK_ALIGNMENT = 1 << @STACK_ALIGNMENT_BITS
82       # Registers used for storing local variables.
83       @LOCAL_REGISTERS = [:r4, :r5, :r6, :r7, :r8, :r10]
84       # Set of registers used for storing local variables.
85       @LOCAL_REGISTERS_SET = Set.new @LOCAL_REGISTERS
86       # Registers to be saved by save-frame.
87       @SAVE_FRAME_REGISTERS = [:r4, :r5, :r6, :r7, :r8,
88                                :r9, :r10, :r11, :r13, :r14]
89       # Hash from register names to offsets in saved frame.
90       @SAVED_FRAME_LAYOUT = {}
91       @SAVE_FRAME_REGISTERS.each_with_index { |r,i| @SAVED_FRAME_LAYOUT[r] = i }
92       @INITIAL_FRAME_SIZE = 2 * @WORDSIZE
93       @NREGISTER_ARGS = 4
94       @NREGISTER_LOCALS = @LOCAL_REGISTERS.length
95       @FP = :r11
96       @RETURN = :r0
97       @TEMPORARIES = [:r12, :r3, :r2, :r1]
98       @constants = []
99       @frame_offset = 0
100       @frame_size = 0
101       @function_end_label = nil
102       @if_labels = []
103       @saved_registers = []       # registers we've saved in the current frame
104       @saved_size = 0             # bytes dedicated to saved registers
105       super params
106       @output_file_suffix = '.s'
107       @features.merge! \
108         :'bits-per-word' => '32',
109         :'byte-order' => 'little-endian',
110         :'bytes-per-word' => 4
111     end
113     # Create an entry in the constants table,
114     # returning the label that will refer to the constant.
115     # The value may be an integer or a label.
116     def add_constant value
117       label = gensym
118       @constants << [label, value]
119       label
120     end
122     # Returns the fp-relative offset for the nth (0-based) argument.
123     def arg_offset n
124       (n - @NREGISTER_ARGS) * @WORDSIZE
125     end
126     
127     # Returns an fp-relative reference for the nth (0-based) argument.
128     def arg_reference n
129       offset_reference arg_offset(n)
130     end
132     # Return the register in which the nth (0-based) argument is stored, or
133     # nil if not stored in a register
134     def arg_register n
135       if n < @NREGISTER_ARGS
136         # We copied the argument to one of the local registers.
137         @LOCAL_REGISTERS[n]
138       else
139         nil
140       end
141     end
143     def auto_bytes value, register
144       if value.kind_of? Integer
145         grow_frame value
146       else
147         temporary = register == :sp ? @TEMPORARIES[0] : register
148         load_value_into_register value, temporary
149         auto_bytes_register temporary
150       end
151       emit "cpy #{register}, sp\n" unless register == :sp
152     end
153     
154     # auto-bytes where the value is supplied in a register and the return
155     # value will be in sp. register must not be sp.
156     def auto_bytes_register register
157       temporary = register == @TEMPORARIES[0] ? :r3 : @TEMPORARIES[0]
158       emit "add #{register}, #{register}, \##{@STACK_ALIGNMENT - 1}\n"
159       emit "mvn #{temporary}, \##{@STACK_ALIGNMENT - 1}\n"
160       emit "and #{register}, #{register}, #{temporary}\n"
161       emit "sub sp, #{register}\n"
162     end
163     
164     def auto_words value, register
165       if value.kind_of? Integer
166         auto_bytes(value * @WORDSIZE, register)
167       else
168         raise "Can't use :sp as a register for auto_words" if register == :sp
169         load_value_into_register value, register
170         emit "lsl #{register}, #{register}, \##{@WORDSIZE_BITS}\n"
171         auto_bytes_register register
172         emit "cpy #{register}, sp\n"
173       end
174     end
175     
176     # Begins a new block.
177     def begin_block *code
178       # If we are starting a block at top level, create a frame
179       if @environment == @top_level
180         nlocals = count_locals code
181         create_frame nlocals, false
182       end
183       @environment = Environment.new @environment
184     end
186     # Emit function prologue and declare _formals_ as function arguments
187     def begin_function formals, nlocals
188       if @environment != @top_level
189         raise "Can only begin a function at top level"
190       end
192       @function_end_label = gensym
193       environment = Environment.new @environment
194       formals.each_with_index do |formal, i|
195         if i < @NREGISTER_ARGS
196           environment.add_arg formal, arg_register(i)
197         else
198           environment.add_arg formal, arg_offset(i)
199         end
200       end
201       @environment = environment
202       emit_function_prologue formals, nlocals
203     end
205     # Define a byte with the given value
206     def byte value
207       emit ".byte #{value}\n"
208     end
210     # Call a function.
211     def call func, *args
212       # Calculate how many arguments need to be pushed on
213       # the stack, and allocate space for them.
214       nstack_args = number_of_stack_arguments args.length
215       old_frame_offset = @frame_offset
216       old_frame_size = @frame_size
217       grow_frame nstack_args if nstack_args > 0
219       # Put stack arguments on the stack
220       (@NREGISTER_ARGS...args.length).each do |n|
221         with_temporary do |temporary|
222           load_value_into_register args[n], temporary
223           emit "str #{temporary}, " +
224             "[sp , \##{(n - @NREGISTER_ARGS) * @WORDSIZE}]\n"
225         end
226       end
228       # Put register arguments in the right registers
229       nregister_args = number_of_register_arguments args.length
230       nregister_args.times do |n|
231           load_value_into_register args[n], :"r#{n}"        
232       end
234       # Call function
235       if global? func
236         @symbol_tracker.use func
237         emit "bl #{func}\n"
238       else
239         with_temporary do |temporary|
240           func_reg = load_value func, temporary
241           emit "blx #{func_reg}\n"
242         end
243       end
245       # Restore original stack frame
246       if old_frame_size != @frame_size
247         emit "add sp, sp, \##{@frame_size - old_frame_size}\n"
248         @frame_offset = old_frame_offset
249         @frame_size = old_frame_size
250       end
251     end
253     # Creates a stack frame for the given number of arguments
254     # and local variables.
255     def create_frame nvars, save_lr = true
256       # Calculate how many variables we will store in registers,
257       # and how many on the stack.
258       nregister_vars = [nvars, @NREGISTER_LOCALS].min
259       nstack_vars = nvars - nregister_vars
261       # Save the registers we will clobber to the stack.
262       clobbered = []
263       nregister_vars.times do |i|
264         clobbered << @LOCAL_REGISTERS[i]
265       end
266       clobbered << @FP
267       clobbered << :lr if save_lr
268       @saved_registers = clobbered
269       @saved_size = @saved_registers.length * @WORDSIZE
270       emit "stmfd sp!, {#{clobbered.join ', '}}\n"
271       emit "add #{@FP}, sp, \##{clobbered.length * @WORDSIZE}\n"
273       # Calculate frame size so that the stack pointer will
274       # be properly aligned at the end of emit_function_prologue.
275       @frame_size = stack_align((clobbered.length + nstack_vars) * @WORDSIZE)
276       extra_space = @frame_size - clobbered.length * @WORDSIZE
277       if extra_space > 0
278         emit "sub sp, sp, \##{extra_space}\n"
279       end
280       @frame_offset = 0
281     end
283     # Emits a comment.
284     def comment text
285       emit "# #{text}\n"
286     end
288     # Start a conditional using the specified branch instruction
289     # after the comparison.
290     def common_if comp, x, y = nil
291       with_temporary do |temporary|
292         xreg = load_value x, temporary
293         yreg = load_value y, :a4
295         falselabel = @environment.gensym
296         @if_labels.push falselabel
298         emit "cmp #{xreg}, #{yreg}\n"
299         lut = { :ifeq => "bne", :ifge => "blt", :ifgt => "ble",
300           :ifle => "bgt", :iflt => "bge", :ifne => "beq" }
301         emit "#{lut[comp]} #{falselabel}\n"
302       end
303     end
305     # Destroys the current stack frame.
306     # If ret is true, loads the saved value of lr into pc.
307     def destroy_frame ret = false
308       # Set sp back to where saved registers were stored
309       saved = @saved_registers
310       emit "sub sp, #{@FP}, \##{saved.length * @WORDSIZE}\n"
312       if ret
313         index = saved.index :lr
314         if index
315           saved[index] = :pc
316         else
317           raise "Request to load saved lr into pc, but lr has not been saved"
318         end
319       end
320       emit "ldmfd sp!, {#{saved.join ', '}}\n"
321       
322       emit_constants if ret
323     end
325     # Aligns on the next multiple of +n+ bytes.
326     def emit_align n
327       emit ".align #{n}\n"
328     end
330     # Writes any constants that need to be written to the instruction
331     # stream, and clears the list of constants that need to be written.
332     def emit_constants
333       @constants.each do |x|
334         label x[0]
335         word x[1]
336       end
337       @constants = []
338     end
340     # Declares symbols to be exported.
341     def emit_export *symbols
342       symbols.each { |sym| emit ".globl #{sym}\n" }
343     end
345     # Emit function prologue.
346     def emit_function_prologue formals = [], nlocals = 0
347       # Calculate the number of arguments we were passed in
348       # registers, the total number of values we need to save
349       # on the stack, then create a stack frame and save
350       # the registers we will be using.
351       nregister_args = [formals.length, @NREGISTER_ARGS].min
352       nvars = nregister_args + nlocals
353       create_frame nvars, true
355       # Move arguments that were passed in registers into
356       # callee-save registers.
357       nregister_args.times do |i|
358         emit "cpy #{@LOCAL_REGISTERS[i]}, r#{i}\n"
359       end
360     end
362     # Emits a label type annotation.
363     def emit_label_type name, type
364       type_map = {
365         :code => "%function",
366         :data => "%object",
367       }
368       emit ".type #{name}, #{type_map[type]}\n"
369     end
371     # Emits a label size annotation.
372     def emit_label_size name
373       emit ".size #{name}, .-#{name}\n"
374     end
376     # Loads a word into a register.
377     def emit_load_word register, base, offset
378       if offset == 0
379         emit "ldr #{register}, [#{base}]\n"
380       else
381         emit "ldr #{register}, [#{base}, \##{offset * @WORDSIZE}]\n"
382       end
383     end
385     # Stores the value of a register in memory.
386     def emit_store_word register, base, offset
387       if offset == 0
388         emit "str #{register}, [#{base}]\n"
389       else
390         emit "str #{register}, [#{base}, \##{offset * @WORDSIZE}]\n"
391       end
392     end
394     # Ends the current block.
395     def end_block
396       # If we are returning to top level, restore stack pointer
397       # and saved registers.
398       if @environment.parent == @top_level
399         offset = @frame_size - @saved_size
400         if offset > 0
401           emit "add sp, sp, \##{offset}\n"
402         end
403         emit "ldmfd sp!, {#{@saved_registers.join ', '}}\n"
404         @frame_size = 0
405         @frame_offset = 0
406         @saved_registers = []
407         @saved_size = 0
409         # If we need to emit constants, do so now
410         unless @constants.empty?
411           lbl = gensym
412           goto lbl
413           label lbl
414         end
415       end
417       # Restore old value of @environment
418       @environment = @environment.parent
419     end
421     # Ends a function body.
422     def end_function
423       if @environment == @top_level
424         raise "Cannot end function when not in a function"
425       end
427       label @function_end_label
429       destroy_frame true
430       @frame_size = 0
431       @frame_offset = 0
432       @saved_registers = []
433       @saved_size = 0
434       @environment = @top_level
435     end
437     # Ends a conditional.
438     def end_if
439       label @if_labels.pop
440     end
442     # Evaluate the binary operation expr and store the result in register
443     def eval_binop expr, register
444       op = expr[0]
446       # Emulation for div and mod, which ARM does not have instructions for
447       case op
448       when :div
449         func = :"__aeabi_idiv"
450         import func unless @relocated_symbols.member? func
451         call func, expr[1], expr[2]
452         emit "cpy #{register}, r0\n" if register != :r0
453         return
454       when :mod
455         func = :"__aeabi_idivmod"
456         import func unless @relocated_symbols.member? func
457         call func, expr[1], expr[2]
458         emit "cpy #{register}, r1\n" if register != :r1
459         return
460       end
462       with_temporaries(2) do |t1,t2|
463         x = load_value expr[1], t1
465         case op
466         when :mul
467           # Operand must be in a register for these ops.
468           y = load_value expr[2], t2
469         else
470           y = value_ref expr[2], t2
471         end
473         case op
474         when :bsr
475           emit "lsr #{register}, #{x}, #{y}\n"
476         when :or
477             emit "orr #{register}, #{x}, #{y}\n"
478         when :mul
479           # Can't store result in same register as first operand.
480           if register == x
481             if x == y
482               # All using the same register. Move x to a different
483               # register to make this work.
484               temp = (x == t1) ? t2 : t1
485               emit "cpy #{temp}, #{x}\n"
486               emit "mul #{register}, #{temp}, #{y}\n"
487             else
488               # Multiplication is commutative. Just swap x and y.
489               emit "mul #{register}, #{y}, #{x}\n"
490             end
491           else
492             # Common case, register and x are different.
493             emit "mul #{register}, #{x}, #{y}\n"
494           end
495         when :rol
496           if integer? expr[2]
497             y = "\##{32 - expr[2]}"
498           else
499             emit "rsb #{y}, #{y}, #32\n"
500           end
501           emit "ror #{register}, #{x}, #{y}\n"
502         when :shl
503           emit "lsl #{register}, #{x}, #{y}\n"
504         when :shr
505           emit "lsr #{register}, #{x}, #{y}\n"
506         when :xor
507           emit "eor #{register}, #{x}, #{y}\n"
508         else
509           emit "#{expr[0]} #{register}, #{x}, #{y}\n"
510         end
511       end
512     end
514     # Evaluates the expression +expr+ and stores the result in +register+.
515     def eval_expr expr, register
516       if expr.length == 1
517         # Load value
518         load_value_into_register expr[0], register
519       else
520         # Evaluate expression
521         op = expr[0]
522         case op
523         when :'auto-bytes'
524           auto_bytes expr[1], register
525         when :'auto-words'
526           auto_words expr[1], register
527         when :call
528           call *expr[1..-1]
529           emit "cpy #{register}, #{@RETURN}\n" if register != @RETURN
530         when :'get-byte'
531           get_byte expr[1], expr[2], register
532         when :'get-word'
533           get_word expr[1], expr[2], register
534         when :not
535           load_value_into_register expr[1], register
536           with_temporary do |temporary|
537             emit "mvn #{temporary}, #0\n"
538             emit "eor #{register}, #{register}, #{temporary}\n"
539           end
540         else
541           if binop? op
542             eval_binop expr, register
543           else
544             raise "Not a magic word: #{op}"
545           end
546         end
547       end
548     end
550     # Load byte from _base_ + _offset_ into _register_
551     def get_byte base, offset, register
552       # If base is an integer, but offset isn't, swap them
553       if !integer?(offset) && integer?(base)
554         base, offset = [offset, base]
555       end
557       if integer? offset
558         with_temporary do |temporary|
559           base_reg = load_value base, temporary
560           if offset == 0
561             emit "ldrb #{register}, [#{base_reg}]\n"
562           else
563             emit "ldrb #{register}, [#{base_reg}, \##{offset}]\n"
564           end
565         end
566       else
567         with_temporaries(2) do |t1,t2|
568           base_reg = load_value base, t1
569           offset_reg = load_value offset, t2
570           emit "ldrb #{register}, [#{base_reg}, #{offset_reg}]\n"
571         end
572       end
573     end
575     # Load word from _base_ + _offset_ * _@WORDSIZE_ into _register_
576     def get_word base, offset, register
577       if integer? offset
578         with_temporary do |temporary|
579           base_reg = load_value base, temporary
580           if offset == 0
581             emit "ldr #{register}, [#{base_reg}]\n"
582           else
583             emit "ldr #{register}, [#{base_reg}, \##{offset * @WORDSIZE}]\n"
584           end
585         end
586       else
587         with_temporaries(2) do |t1,t2|
588           base_reg = load_value base, t1
589           offset_reg = load_value offset, t2
590           emit "ldr #{register}, [#{base_reg}, #{offset_reg}, LSL #2]\n"
591         end
592       end
593     end
595     # Jump to a label.
596     def goto label
597       if global? label
598         emit "b #{label}\n"
599       else
600         with_temporary do |temporary|
601           register = load_value label, temporary
602           emit "cpy pc, #{register}\n"
603         end
604       end
606       # If we have constants that need to be emitted, do so now
607       emit_constants
608     end
610     # Grows the current frame by n words, plus padding to
611     # respect alignment rules.
612     def grow_frame nwords
613       increment = stack_align(nwords * @WORDSIZE)
614       emit "sub sp, sp, \##{increment}\n"
615       @frame_size = @frame_size + increment
616       @frame_offset = @frame_offset + increment
617     end
619     # Start the false path of a conditional.
620     def ifelse
621       newlabel = @environment.gensym
622       goto newlabel
623       lbl = @if_labels.pop
624       label lbl
625       @if_labels.push newlabel
626     end
628     # Test if x is equal to y
629     def ifeq x, y
630       common_if :ifeq, x, y
631     end
633     # Test if x is greater than or equal to y
634     def ifge x, y
635       common_if :ifge, x, y
636     end
638     # Test if x is strictly greater than y
639     def ifgt x, y
640       common_if :ifgt, x, y
641     end
643     # Test if x is less than or equal to y
644     def ifle x, y
645       common_if :ifle, x, y
646     end
648     # Test if x is strictly less than y
649     def iflt x, y
650       common_if :iflt, x, y
651     end
653     # Test if x different from y
654     def ifne x, y
655       common_if :ifne, x, y
656     end
658     # Introduce a new local variable
659     def let symbol, *expr
660       n = @environment.locals
661       register = local_register n
663       if register
664         # We will use a register to store the value
665         @environment.add_local symbol, register
666         eval_expr expr, register
667       else
668         # We will use the stack to store the value
669         offset = local_offset n
670         @environment.add_local symbol, offset
671         with_temporary do |temporary|
672           eval_expr expr, temporary
673           emit "str #{temporary}, #{offset_reference offset}\n"
674         end
675       end
676     end
678     # Loads the value at the given address.
679     def load_at address, register
680       load_value_into_register address, register
681       emit "ldr #{register}, [#{register}]\n"
682       register
683     end
685     # Loads a value into some register.
686     # If the value is already in a register, does nothing.
687     # Else, loads the value into the register given as the
688     # second argument.
689     # Returns the name of the register the value is in.
690     def load_value x, register
691       ref = value_ref x, register
692       if register? ref
693         ref
694       else
695         emit "mov #{register}, #{ref}\n"
696         register
697       end
698     end
700     # Loads a value into a specific register.
701     def load_value_into_register x, register
702       ref = value_ref x, register
703       if ref != register
704         if register? ref
705           emit "cpy #{register}, #{ref}\n"
706         else
707           emit "mov #{register}, #{ref}\n"
708         end
709       end
710       register
711     end
713     # Returns the fp-relative reference for the nth (0-based) local.
714     def local_offset n
715       nstack_locals = n + number_of_register_arguments - @NREGISTER_LOCALS
716       -(nstack_locals + 1) * @WORDSIZE - @saved_size
717     end
718     
719     # Given an offset, returns an fp-relative reference.
720     def offset_reference offset
721       "[#{@FP}, \##{offset}]"
722     end
724     # Returns true if the nth (0-based) local is stored in a register
725     def register_local? n
726       (n + number_of_register_arguments) < @NREGISTER_LOCALS
727     end
729     # Returns from a function.
730     # 
731     # _words_ may contain an expression to be evaluated. The result
732     # of the evaluation is returned from the function.
733     def ret *words
734       # Compute return value and store it in @RETURN
735       eval_expr(words, @RETURN) unless words.empty?
736       # Go to epilogue
737       goto @function_end_label
738     end
740     # Set a variable to the result of evaluating an expression
741     def set symbol, *expr
742       if at_expr? symbol
743         with_temporaries(2) do |t1,t2|
744           eval_expr expr, t1
745           register = load_value symbol[1], t2
746           emit "str #{t1}, [#{register}]\n"
747         end
748       else
749         x = @environment[symbol]
750         if x == nil
751           raise "Cannot change value of constant #{symbol}"
752         elsif x.kind_of? Symbol
753           eval_expr expr, x
754         else
755           with_temporary do |temporary|
756             eval_expr expr, temporary
757             emit "str #{temporary}, #{offset_reference x}\n"
758           end
759         end
760       end
761     end
763     # Set the byte at _base_ + _offset_ to _value_
764     def set_byte base, offset, value
765       # If base is an integer, but offset isn't, swap them
766       if !integer?(offset) && integer?(base)
767         base, offset = [offset, base]
768       end
770       if integer? offset
771         base_reg = load_value base, :a4
772         with_temporary do |temporary|
773           load_value_into_register value, temporary
774           if offset == 0
775             emit "strb #{temporary}, [#{base_reg}]\n"
776           else
777             emit "strb #{temporary}, [#{base_reg}, \##{offset}]\n"
778           end
779         end
780       else
781         eval_binop [:add, base, offset], :a4
782         with_temporary do |temporary|
783           load_value_into_register value, temporary
784           emit "strb #{temporary}, [a4]\n"
785         end
786       end
787     end
789     # Set the word at _base_ + _offset_ * +@WORDSIZE+ to _value_
790     def set_word base, offset, value
791       # If base is an integer, but offset isn't, swap them
792       if !integer?(offset) && integer?(base)
793         base, offset = [offset, base]
794       end
796       if integer? offset
797         base_reg = load_value base, :a4
798         with_temporary do |temporary|
799           load_value_into_register value, temporary
800           if offset == 0
801             emit "str #{temporary}, [#{base_reg}]\n"
802           else
803             emit "str #{temporary}, [#{base_reg}, \##{offset * @WORDSIZE}]\n"
804           end
805         end
806       else
807         load_value_into_register base, :a4
808         with_temporary do |temporary|
809           load_value_into_register offset, temporary
810           emit "add a4, a4, #{temporary}, LSL #2\n"
811           load_value_into_register value, temporary
812           emit "str #{temporary}, [a4]\n"
813         end
814       end
815     end
817     # Define a string with the given value
818     def string value
819       code = ''
820       value.each_byte do |b|
821         if b == 92
822           code << "\\\\"
823         elsif b >= 32 && b < 127 && b != 34
824           code << b.chr
825         else
826           code << sprintf("\\%03o", b)
827         end
828       end
829       emit ".ascii \"#{code}\"\n"
830     end
832     # Call a function, re-using the current call frame if possible.
833     def tail_call func, *args
834       # Compute number of stack arguments
835       nstackargs = number_of_stack_arguments args.length
836       # If we need more stack arguments than we have now,
837       # perform a normal call and return
838       if nstackargs > number_of_stack_arguments(@environment.args)
839         emit "# Not enough space for proper tail call; using regular call\n"
840         ret :call, func, *args
841       end
843       # We will assign arguments from left to right.
844       # Find places that we will overwrite before we read them,
845       # and store their values in some newly allocated stack space.
846       old_frame_offset = @frame_offset
847       old_frame_size = @frame_size
848       overwritten = {}
849       (@NREGISTER_ARGS...args.length).each do |i|
850         arg = args[i]
851         arg = arg[1] if at_expr? arg
852         if symbol?(arg)
853           binding = @environment[arg]
854           if binding[0] == :arg && binding[1] >= @NREGISTER_ARGS &&
855               binding[1] < i
856             # Argument i is a stack argument, but the value we will assign
857             # it is a stack argument that comes before it, so we will
858             # have overwritten it by the time we get to it.
859             overwritten[arg] = nil
860           end
861         end
862       end
863       
864       unless overwritten.empty?
865         # Allocate space for arguments to be saved
866         grow_frame overwritten.length
867         # Save values
868         offset = 0
869         overwritten.each_key do |key|
870           reg = load_value key
871           emit "str #{reg}, [sp, \##{offset}]\n"
872           overwritten[key] = offset
873           offset = offset + @WORDSIZE
874         end
875       end
877       # Assign arguments
878       args.each_index do |i|
879         arg = args[i]
880         if register_arg? i
881           load_value_into_register arg, "a#{i + 1}"
882         else
883           # Test if this is a value we saved
884           sym = at_expr?(arg) ? arg[1] : arg
885           saved = overwritten[sym]
886           if saved
887             # Saved value, load from stack
888             with_temporary do |temporary|
889               emit "ldr #{temporary}, [sp, \##{saved}]\n"
890               emit "str #{temporary}, #{arg_reference i}\n"
891             end
892           else
893             # Regular value, use load_value
894             with_temporary do |temporary|
895               reg = load_value arg, temporary
896               emit "str #{reg}, #{arg_reference i}\n"
897             end
898           end
899         end
900       end
902       with_temporary do |temporary|
903         # Load address of function to be called
904         load_value_into_register func, temporary
906         # Destroy current activation frame and enter func
907         destroy_frame false
908         emit "bx #{temporary}\n"
909       end
910       emit_constants
911     end
913     # Returns a reference to a value.
914     # For immediate values that fit in 8 bits, this returns the
915     # value itself (in ARM syntax).
916     # For all other values, loads the value into a register and
917     # returns the name of the register. If the value is already
918     # in a register, the name of that register is returned. Else,
919     # the value is loaded into the register specified as the
920     # second argument.
921     def value_ref x, register
922       if substitution? x
923         x = substitute_number x[1]
924       end
925         
926       if integer? x
927         if x >= 0 && x <= 255
928           return "\##{x}"
929         elsif x >= -255 && x < 0
930           emit "mvn #{register}, \##{-(x + 1)}\n"
931           return register
932         else
933           lbl = add_constant x
934           emit "ldr #{register}, #{lbl}\n"
935           return register
936         end
937       elsif symbol? x
938         binding = @environment[x]
939         if binding.kind_of? Symbol
940           # Value is already in a register. Return register name.
941           return binding
942         elsif binding.kind_of? Integer
943           # Value is on the stack. Load from the stack.
944           emit "ldr #{register}, #{offset_reference binding}\n"
945           return register
946         else
947           # Assume global
948           @symbol_tracker.use x
949           lbl = add_constant x
950           emit "ldr #{register}, #{lbl}\n"
951           return register
952         end
953       elsif at_expr? x
954         load_at x[1], register
955       else
956         raise "Don't know how to load #{x.inspect}"
957       end
958     end
960     # Define a word with the given value
961     def word value
962       emit ".int #{value}\n"
963     end
965   end
967   # Register class for little endian ARM
968   Voodoo::CodeGenerator.register_generator ARMGasGenerator,
969                                            :architecture => :arm,
970                                            :format => :gas