reject programs that use symbols that have not been defined or imported
[voodoo-lang.git] / lib / voodoo / generators / arm_gas_generator.rb
blob5cd847064ce1be25569ea3e02adc57b49435f254
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       @imports = Set.new
103       @if_labels = []
104       @saved_registers = []       # registers we've saved in the current frame
105       @saved_size = 0             # bytes dedicated to saved registers
106       super params
107       @output_file_suffix = '.s'
108       @features.merge! \
109         :'bits-per-word' => '32',
110         :'byte-order' => 'little-endian',
111         :'bytes-per-word' => 4
112     end
114     # Create an entry in the constants table,
115     # returning the label that will refer to the constant.
116     # The value may be an integer or a label.
117     def add_constant value
118       label = gensym
119       @constants << [label, value]
120       label
121     end
123     # Returns the fp-relative offset for the nth (0-based) argument.
124     def arg_offset n
125       (n - @NREGISTER_ARGS) * @WORDSIZE
126     end
127     
128     # Returns an fp-relative reference for the nth (0-based) argument.
129     def arg_reference n
130       offset_reference arg_offset(n)
131     end
133     # Return the register in which the nth (0-based) argument is stored, or
134     # nil if not stored in a register
135     def arg_register n
136       if n < @NREGISTER_ARGS
137         # We copied the argument to one of the local registers.
138         @LOCAL_REGISTERS[n]
139       else
140         nil
141       end
142     end
144     def auto_bytes value, register
145       if value.kind_of? Integer
146         grow_frame value
147       else
148         temporary = register == :sp ? @TEMPORARIES[0] : register
149         load_value_into_register value, temporary
150         auto_bytes_register temporary
151       end
152       emit "cpy #{register}, sp\n" unless register == :sp
153     end
154     
155     # auto-bytes where the value is supplied in a register and the return
156     # value will be in sp. register must not be sp.
157     def auto_bytes_register register
158       temporary = register == @TEMPORARIES[0] ? :r3 : @TEMPORARIES[0]
159       emit "add #{register}, #{register}, \##{@STACK_ALIGNMENT - 1}\n"
160       emit "mvn #{temporary}, \##{@STACK_ALIGNMENT - 1}\n"
161       emit "and #{register}, #{register}, #{temporary}\n"
162       emit "sub sp, #{register}\n"
163     end
164     
165     def auto_words value, register
166       if value.kind_of? Integer
167         auto_bytes(value * @WORDSIZE, register)
168       else
169         raise "Can't use :sp as a register for auto_words" if register == :sp
170         load_value_into_register value, register
171         emit "lsl #{register}, #{register}, \##{@WORDSIZE_BITS}\n"
172         auto_bytes_register register
173         emit "cpy #{register}, sp\n"
174       end
175     end
176     
177     # Begins a new block.
178     def begin_block *code
179       # If we are starting a block at top level, create a frame
180       if @environment == @top_level
181         nlocals = count_locals code
182         create_frame nlocals, false
183       end
184       @environment = Environment.new @environment
185     end
187     # Emit function prologue and declare _formals_ as function arguments
188     def begin_function formals, nlocals
189       if @environment != @top_level
190         raise "Can only begin a function at top level"
191       end
193       @function_end_label = gensym
194       environment = Environment.new @environment
195       formals.each_with_index do |formal, i|
196         if i < @NREGISTER_ARGS
197           environment.add_arg formal, arg_register(i)
198         else
199           environment.add_arg formal, arg_offset(i)
200         end
201       end
202       @environment = environment
203       emit_function_prologue formals, nlocals
204     end
206     # Define a byte with the given value
207     def byte value
208       emit ".byte #{value}\n"
209     end
211     # Call a function.
212     def call func, *args
213       # Calculate how many arguments need to be pushed on
214       # the stack, and allocate space for them.
215       nstack_args = number_of_stack_arguments args.length
216       old_frame_offset = @frame_offset
217       old_frame_size = @frame_size
218       grow_frame nstack_args if nstack_args > 0
220       # Put stack arguments on the stack
221       (@NREGISTER_ARGS...args.length).each do |n|
222         with_temporary do |temporary|
223           load_value_into_register args[n], temporary
224           emit "str #{temporary}, " +
225             "[sp , \##{(n - @NREGISTER_ARGS) * @WORDSIZE}]\n"
226         end
227       end
229       # Put register arguments in the right registers
230       nregister_args = number_of_register_arguments args.length
231       nregister_args.times do |n|
232           load_value_into_register args[n], :"r#{n}"        
233       end
235       # Call function
236       if global? func
237         @symbol_tracker.use func
238         emit "bl #{func}\n"
239       else
240         with_temporary do |temporary|
241           func_reg = load_value func, temporary
242           emit "blx #{func_reg}\n"
243         end
244       end
246       # Restore original stack frame
247       if old_frame_size != @frame_size
248         emit "add sp, sp, \##{@frame_size - old_frame_size}\n"
249         @frame_offset = old_frame_offset
250         @frame_size = old_frame_size
251       end
252     end
254     # Creates a stack frame for the given number of arguments
255     # and local variables.
256     def create_frame nvars, save_lr = true
257       # Calculate how many variables we will store in registers,
258       # and how many on the stack.
259       nregister_vars = [nvars, @NREGISTER_LOCALS].min
260       nstack_vars = nvars - nregister_vars
262       # Save the registers we will clobber to the stack.
263       clobbered = []
264       nregister_vars.times do |i|
265         clobbered << @LOCAL_REGISTERS[i]
266       end
267       clobbered << @FP
268       clobbered << :lr if save_lr
269       @saved_registers = clobbered
270       @saved_size = @saved_registers.length * @WORDSIZE
271       emit "stmfd sp!, {#{clobbered.join ', '}}\n"
272       emit "add #{@FP}, sp, \##{clobbered.length * @WORDSIZE}\n"
274       # Calculate frame size so that the stack pointer will
275       # be properly aligned at the end of emit_function_prologue.
276       @frame_size = stack_align((clobbered.length + nstack_vars) * @WORDSIZE)
277       extra_space = @frame_size - clobbered.length * @WORDSIZE
278       if extra_space > 0
279         emit "sub sp, sp, \##{extra_space}\n"
280       end
281       @frame_offset = 0
282     end
284     # Emits a comment.
285     def comment text
286       emit "# #{text}\n"
287     end
289     # Start a conditional using the specified branch instruction
290     # after the comparison.
291     def common_if comp, x, y = nil
292       with_temporary do |temporary|
293         xreg = load_value x, temporary
294         yreg = load_value y, :a4
296         falselabel = @environment.gensym
297         @if_labels.push falselabel
299         emit "cmp #{xreg}, #{yreg}\n"
300         lut = { :ifeq => "bne", :ifge => "blt", :ifgt => "ble",
301           :ifle => "bgt", :iflt => "bge", :ifne => "beq" }
302         emit "#{lut[comp]} #{falselabel}\n"
303       end
304     end
306     # Destroys the current stack frame.
307     # If ret is true, loads the saved value of lr into pc.
308     def destroy_frame ret = false
309       # Set sp back to where saved registers were stored
310       saved = @saved_registers
311       emit "sub sp, #{@FP}, \##{saved.length * @WORDSIZE}\n"
313       if ret
314         index = saved.index :lr
315         if index
316           saved[index] = :pc
317         else
318           raise "Request to load saved lr into pc, but lr has not been saved"
319         end
320       end
321       emit "ldmfd sp!, {#{saved.join ', '}}\n"
322       
323       emit_constants if ret
324     end
326     # Aligns on the next multiple of +n+ bytes.
327     def emit_align n
328       emit ".align #{n}\n"
329     end
331     # Writes any constants that need to be written to the instruction
332     # stream, and clears the list of constants that need to be written.
333     def emit_constants
334       @constants.each do |x|
335         label x[0]
336         word x[1]
337       end
338       @constants = []
339     end
341     # Emit function prologue.
342     def emit_function_prologue formals = [], nlocals = 0
343       # Calculate the number of arguments we were passed in
344       # registers, the total number of values we need to save
345       # on the stack, then create a stack frame and save
346       # the registers we will be using.
347       nregister_args = [formals.length, @NREGISTER_ARGS].min
348       nvars = nregister_args + nlocals
349       create_frame nvars, true
351       # Move arguments that were passed in registers into
352       # callee-save registers.
353       nregister_args.times do |i|
354         emit "cpy #{@LOCAL_REGISTERS[i]}, r#{i}\n"
355       end
356     end
358     # Emits a label type annotation.
359     def emit_label_type name, type
360       type_map = {
361         :code => "%function",
362         :data => "%object",
363       }
364       emit ".type #{name}, #{type_map[type]}\n"
365     end
367     # Emits a label size annotation.
368     def emit_label_size name
369       emit ".size #{name}, .-#{name}\n"
370     end
372     # Loads a word into a register.
373     def emit_load_word register, base, offset
374       if offset == 0
375         emit "ldr #{register}, [#{base}]\n"
376       else
377         emit "ldr #{register}, [#{base}, \##{offset * @WORDSIZE}]\n"
378       end
379     end
381     # Stores the value of a register in memory.
382     def emit_store_word register, base, offset
383       if offset == 0
384         emit "str #{register}, [#{base}]\n"
385       else
386         emit "str #{register}, [#{base}, \##{offset * @WORDSIZE}]\n"
387       end
388     end
390     # Ends the current block.
391     def end_block
392       # If we are returning to top level, restore stack pointer
393       # and saved registers.
394       if @environment.parent == @top_level
395         offset = @frame_size - @saved_size
396         if offset > 0
397           emit "add sp, sp, \##{offset}\n"
398         end
399         emit "ldmfd sp!, {#{@saved_registers.join ', '}}\n"
400         @frame_size = 0
401         @frame_offset = 0
402         @saved_registers = []
403         @saved_size = 0
405         # If we need to emit constants, do so now
406         unless @constants.empty?
407           lbl = gensym
408           goto lbl
409           label lbl
410         end
411       end
413       # Restore old value of @environment
414       @environment = @environment.parent
415     end
417     # Ends a function body.
418     def end_function
419       if @environment == @top_level
420         raise "Cannot end function when not in a function"
421       end
423       label @function_end_label
425       destroy_frame true
426       @frame_size = 0
427       @frame_offset = 0
428       @saved_registers = []
429       @saved_size = 0
430       @environment = @top_level
431     end
433     # Ends a conditional.
434     def end_if
435       label @if_labels.pop
436     end
438     # Evaluate the binary operation expr and store the result in register
439     def eval_binop expr, register
440       op = expr[0]
442       # Emulation for div and mod, which ARM does not have instructions for
443       case op
444       when :div
445         func = :"__aeabi_idiv"
446         import func unless @imports.member? func
447         call func, expr[1], expr[2]
448         emit "cpy #{register}, r0\n" if register != :r0
449         return
450       when :mod
451         func = :"__aeabi_idivmod"
452         import func unless @imports.member? func
453         call func, expr[1], expr[2]
454         emit "cpy #{register}, r1\n" if register != :r1
455         return
456       end
458       with_temporaries(2) do |t1,t2|
459         x = load_value expr[1], t1
461         case op
462         when :mul
463           # Operand must be in a register for these ops.
464           y = load_value expr[2], t2
465         else
466           y = value_ref expr[2], t2
467         end
469         case op
470         when :bsr
471           emit "lsr #{register}, #{x}, #{y}\n"
472         when :or
473             emit "orr #{register}, #{x}, #{y}\n"
474         when :mul
475           # Can't store result in same register as first operand.
476           if register == x
477             if x == y
478               # All using the same register. Move x to a different
479               # register to make this work.
480               temp = (x == t1) ? t2 : t1
481               emit "cpy #{temp}, #{x}\n"
482               emit "mul #{register}, #{temp}, #{y}\n"
483             else
484               # Multiplication is commutative. Just swap x and y.
485               emit "mul #{register}, #{y}, #{x}\n"
486             end
487           else
488             # Common case, register and x are different.
489             emit "mul #{register}, #{x}, #{y}\n"
490           end
491         when :rol
492           if integer? expr[2]
493             y = "\##{32 - expr[2]}"
494           else
495             emit "rsb #{y}, #{y}, #32\n"
496           end
497           emit "ror #{register}, #{x}, #{y}\n"
498         when :shl
499           emit "lsl #{register}, #{x}, #{y}\n"
500         when :shr
501           emit "lsr #{register}, #{x}, #{y}\n"
502         when :xor
503           emit "eor #{register}, #{x}, #{y}\n"
504         else
505           emit "#{expr[0]} #{register}, #{x}, #{y}\n"
506         end
507       end
508     end
510     # Evaluates the expression +expr+ and stores the result in +register+.
511     def eval_expr expr, register
512       if expr.length == 1
513         # Load value
514         load_value_into_register expr[0], register
515       else
516         # Evaluate expression
517         op = expr[0]
518         case op
519         when :'auto-bytes'
520           auto_bytes expr[1], register
521         when :'auto-words'
522           auto_words expr[1], register
523         when :call
524           call *expr[1..-1]
525           emit "cpy #{register}, #{@RETURN}\n" if register != @RETURN
526         when :'get-byte'
527           get_byte expr[1], expr[2], register
528         when :'get-word'
529           get_word expr[1], expr[2], register
530         when :not
531           load_value_into_register expr[1], register
532           with_temporary do |temporary|
533             emit "mvn #{temporary}, #0\n"
534             emit "eor #{register}, #{register}, #{temporary}\n"
535           end
536         else
537           if binop? op
538             eval_binop expr, register
539           else
540             raise "Not a magic word: #{op}"
541           end
542         end
543       end
544     end
546     # Export symbols from the current section
547     def export *symbols
548       symbols.each { |sym| emit ".globl #{sym}\n" }
549     end
551     # Load byte from _base_ + _offset_ into _register_
552     def get_byte base, offset, register
553       # If base is an integer, but offset isn't, swap them
554       if !integer?(offset) && integer?(base)
555         base, offset = [offset, base]
556       end
558       if integer? offset
559         with_temporary do |temporary|
560           base_reg = load_value base, temporary
561           if offset == 0
562             emit "ldrb #{register}, [#{base_reg}]\n"
563           else
564             emit "ldrb #{register}, [#{base_reg}, \##{offset}]\n"
565           end
566         end
567       else
568         with_temporaries(2) do |t1,t2|
569           base_reg = load_value base, t1
570           offset_reg = load_value offset, t2
571           emit "ldrb #{register}, [#{base_reg}, #{offset_reg}]\n"
572         end
573       end
574     end
576     # Load word from _base_ + _offset_ * _@WORDSIZE_ into _register_
577     def get_word base, offset, register
578       if integer? offset
579         with_temporary do |temporary|
580           base_reg = load_value base, temporary
581           if offset == 0
582             emit "ldr #{register}, [#{base_reg}]\n"
583           else
584             emit "ldr #{register}, [#{base_reg}, \##{offset * @WORDSIZE}]\n"
585           end
586         end
587       else
588         with_temporaries(2) do |t1,t2|
589           base_reg = load_value base, t1
590           offset_reg = load_value offset, t2
591           emit "ldr #{register}, [#{base_reg}, #{offset_reg}, LSL #2]\n"
592         end
593       end
594     end
596     # Jump to a label.
597     def goto label
598       if global? label
599         emit "b #{label}\n"
600       else
601         with_temporary do |temporary|
602           register = load_value label, temporary
603           emit "cpy pc, #{register}\n"
604         end
605       end
607       # If we have constants that need to be emitted, do so now
608       emit_constants
609     end
611     # Grows the current frame by n words, plus padding to
612     # respect alignment rules.
613     def grow_frame nwords
614       increment = stack_align(nwords * @WORDSIZE)
615       emit "sub sp, sp, \##{increment}\n"
616       @frame_size = @frame_size + increment
617       @frame_offset = @frame_offset + increment
618     end
620     # Start the false path of a conditional.
621     def ifelse
622       newlabel = @environment.gensym
623       goto newlabel
624       lbl = @if_labels.pop
625       label lbl
626       @if_labels.push newlabel
627     end
629     # Test if x is equal to y
630     def ifeq x, y
631       common_if :ifeq, x, y
632     end
634     # Test if x is greater than or equal to y
635     def ifge x, y
636       common_if :ifge, x, y
637     end
639     # Test if x is strictly greater than y
640     def ifgt x, y
641       common_if :ifgt, x, y
642     end
644     # Test if x is less than or equal to y
645     def ifle x, y
646       common_if :ifle, x, y
647     end
649     # Test if x is strictly less than y
650     def iflt x, y
651       common_if :iflt, x, y
652     end
654     # Test if x different from y
655     def ifne x, y
656       common_if :ifne, x, y
657     end
659     # Import labels into the current section
660     def import *symbols
661       # Record imported labels in @imports and @symbol_tracker
662       @imports.merge symbols
663       @symbol_tracker.define *symbols
664     end
666     # Introduce a new local variable
667     def let symbol, *expr
668       n = @environment.locals
669       register = local_register n
671       if register
672         # We will use a register to store the value
673         @environment.add_local symbol, register
674         eval_expr expr, register
675       else
676         # We will use the stack to store the value
677         offset = local_offset n
678         @environment.add_local symbol, offset
679         with_temporary do |temporary|
680           eval_expr expr, temporary
681           emit "str #{temporary}, #{offset_reference offset}\n"
682         end
683       end
684     end
686     # Loads the value at the given address.
687     def load_at address, register
688       load_value_into_register address, register
689       emit "ldr #{register}, [#{register}]\n"
690       register
691     end
693     # Loads a value into some register.
694     # If the value is already in a register, does nothing.
695     # Else, loads the value into the register given as the
696     # second argument.
697     # Returns the name of the register the value is in.
698     def load_value x, register
699       ref = value_ref x, register
700       if register? ref
701         ref
702       else
703         emit "mov #{register}, #{ref}\n"
704         register
705       end
706     end
708     # Loads a value into a specific register.
709     def load_value_into_register x, register
710       ref = value_ref x, register
711       if ref != register
712         if register? ref
713           emit "cpy #{register}, #{ref}\n"
714         else
715           emit "mov #{register}, #{ref}\n"
716         end
717       end
718       register
719     end
721     # Returns the fp-relative reference for the nth (0-based) local.
722     def local_offset n
723       nstack_locals = n + number_of_register_arguments - @NREGISTER_LOCALS
724       -(nstack_locals + 1) * @WORDSIZE - @saved_size
725     end
726     
727     # Given an offset, returns an fp-relative reference.
728     def offset_reference offset
729       "[#{@FP}, \##{offset}]"
730     end
732     # Returns true if the nth (0-based) local is stored in a register
733     def register_local? n
734       (n + number_of_register_arguments) < @NREGISTER_LOCALS
735     end
737     # Returns from a function.
738     # 
739     # _words_ may contain an expression to be evaluated. The result
740     # of the evaluation is returned from the function.
741     def ret *words
742       # Compute return value and store it in @RETURN
743       eval_expr(words, @RETURN) unless words.empty?
744       # Go to epilogue
745       goto @function_end_label
746     end
748     # Set a variable to the result of evaluating an expression
749     def set symbol, *expr
750       if at_expr? symbol
751         with_temporaries(2) do |t1,t2|
752           eval_expr expr, t1
753           register = load_value symbol[1], t2
754           emit "str #{t1}, [#{register}]\n"
755         end
756       else
757         x = @environment[symbol]
758         if x == nil
759           raise "Cannot change value of constant #{symbol}"
760         elsif x.kind_of? Symbol
761           eval_expr expr, x
762         else
763           with_temporary do |temporary|
764             eval_expr expr, temporary
765             emit "str #{temporary}, #{offset_reference x}\n"
766           end
767         end
768       end
769     end
771     # Set the byte at _base_ + _offset_ to _value_
772     def set_byte base, offset, value
773       # If base is an integer, but offset isn't, swap them
774       if !integer?(offset) && integer?(base)
775         base, offset = [offset, base]
776       end
778       if integer? offset
779         base_reg = load_value base, :a4
780         with_temporary do |temporary|
781           load_value_into_register value, temporary
782           if offset == 0
783             emit "strb #{temporary}, [#{base_reg}]\n"
784           else
785             emit "strb #{temporary}, [#{base_reg}, \##{offset}]\n"
786           end
787         end
788       else
789         eval_binop [:add, base, offset], :a4
790         with_temporary do |temporary|
791           load_value_into_register value, temporary
792           emit "strb #{temporary}, [a4]\n"
793         end
794       end
795     end
797     # Set the word at _base_ + _offset_ * +@WORDSIZE+ to _value_
798     def set_word base, offset, value
799       # If base is an integer, but offset isn't, swap them
800       if !integer?(offset) && integer?(base)
801         base, offset = [offset, base]
802       end
804       if integer? offset
805         base_reg = load_value base, :a4
806         with_temporary do |temporary|
807           load_value_into_register value, temporary
808           if offset == 0
809             emit "str #{temporary}, [#{base_reg}]\n"
810           else
811             emit "str #{temporary}, [#{base_reg}, \##{offset * @WORDSIZE}]\n"
812           end
813         end
814       else
815         load_value_into_register base, :a4
816         with_temporary do |temporary|
817           load_value_into_register offset, temporary
818           emit "add a4, a4, #{temporary}, LSL #2\n"
819           load_value_into_register value, temporary
820           emit "str #{temporary}, [a4]\n"
821         end
822       end
823     end
825     # Define a string with the given value
826     def string value
827       code = ''
828       value.each_byte do |b|
829         if b == 92
830           code << "\\\\"
831         elsif b >= 32 && b < 127 && b != 34
832           code << b.chr
833         else
834           code << sprintf("\\%03o", b)
835         end
836       end
837       emit ".ascii \"#{code}\"\n"
838     end
840     # Call a function, re-using the current call frame if possible.
841     def tail_call func, *args
842       # Compute number of stack arguments
843       nstackargs = number_of_stack_arguments args.length
844       # If we need more stack arguments than we have now,
845       # perform a normal call and return
846       if nstackargs > number_of_stack_arguments(@environment.args)
847         emit "# Not enough space for proper tail call; using regular call\n"
848         ret :call, func, *args
849       end
851       # We will assign arguments from left to right.
852       # Find places that we will overwrite before we read them,
853       # and store their values in some newly allocated stack space.
854       old_frame_offset = @frame_offset
855       old_frame_size = @frame_size
856       overwritten = {}
857       (@NREGISTER_ARGS...args.length).each do |i|
858         arg = args[i]
859         arg = arg[1] if at_expr? arg
860         if symbol?(arg)
861           binding = @environment[arg]
862           if binding[0] == :arg && binding[1] >= @NREGISTER_ARGS &&
863               binding[1] < i
864             # Argument i is a stack argument, but the value we will assign
865             # it is a stack argument that comes before it, so we will
866             # have overwritten it by the time we get to it.
867             overwritten[arg] = nil
868           end
869         end
870       end
871       
872       unless overwritten.empty?
873         # Allocate space for arguments to be saved
874         grow_frame overwritten.length
875         # Save values
876         offset = 0
877         overwritten.each_key do |key|
878           reg = load_value key
879           emit "str #{reg}, [sp, \##{offset}]\n"
880           overwritten[key] = offset
881           offset = offset + @WORDSIZE
882         end
883       end
885       # Assign arguments
886       args.each_index do |i|
887         arg = args[i]
888         if register_arg? i
889           load_value_into_register arg, "a#{i + 1}"
890         else
891           # Test if this is a value we saved
892           sym = at_expr?(arg) ? arg[1] : arg
893           saved = overwritten[sym]
894           if saved
895             # Saved value, load from stack
896             with_temporary do |temporary|
897               emit "ldr #{temporary}, [sp, \##{saved}]\n"
898               emit "str #{temporary}, #{arg_reference i}\n"
899             end
900           else
901             # Regular value, use load_value
902             with_temporary do |temporary|
903               reg = load_value arg, temporary
904               emit "str #{reg}, #{arg_reference i}\n"
905             end
906           end
907         end
908       end
910       with_temporary do |temporary|
911         # Load address of function to be called
912         load_value_into_register func, temporary
914         # Destroy current activation frame and enter func
915         destroy_frame false
916         emit "bx #{temporary}\n"
917       end
918       emit_constants
919     end
921     # Returns a reference to a value.
922     # For immediate values that fit in 8 bits, this returns the
923     # value itself (in ARM syntax).
924     # For all other values, loads the value into a register and
925     # returns the name of the register. If the value is already
926     # in a register, the name of that register is returned. Else,
927     # the value is loaded into the register specified as the
928     # second argument.
929     def value_ref x, register
930       if substitution? x
931         x = substitute_number x[1]
932       end
933         
934       if integer? x
935         if x >= 0 && x <= 255
936           return "\##{x}"
937         elsif x >= -255 && x < 0
938           emit "mvn #{register}, \##{-(x + 1)}\n"
939           return register
940         else
941           lbl = add_constant x
942           emit "ldr #{register}, #{lbl}\n"
943           return register
944         end
945       elsif symbol? x
946         binding = @environment[x]
947         if binding.kind_of? Symbol
948           # Value is already in a register. Return register name.
949           return binding
950         elsif binding.kind_of? Integer
951           # Value is on the stack. Load from the stack.
952           emit "ldr #{register}, #{offset_reference binding}\n"
953           return register
954         else
955           # Assume global
956           @symbol_tracker.use x
957           lbl = add_constant x
958           emit "ldr #{register}, #{lbl}\n"
959           return register
960         end
961       elsif at_expr? x
962         load_at x[1], register
963       else
964         raise "Don't know how to load #{x.inspect}"
965       end
966     end
968     # Define a word with the given value
969     def word value
970       emit ".int #{value}\n"
971     end
973   end
975   # Register class for little endian ARM
976   Voodoo::CodeGenerator.register_generator ARMGasGenerator,
977                                            :architecture => :arm,
978                                            :format => :gas