From 69d2545ae87eb5c6997cc910027d7183ae14997b Mon Sep 17 00:00:00 2001 From: inglorion Date: Fri, 5 Oct 2012 06:57:03 +0200 Subject: [PATCH] Update MIPS code generator to work with refactored environment --- lib/voodoo/generators/mips_gas_generator.rb | 109 +++++++++++----------------- 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/lib/voodoo/generators/mips_gas_generator.rb b/lib/voodoo/generators/mips_gas_generator.rb index 02c49f5..ebf9c34 100644 --- a/lib/voodoo/generators/mips_gas_generator.rb +++ b/lib/voodoo/generators/mips_gas_generator.rb @@ -149,15 +149,15 @@ module Voodoo emit ".align #{alignment}\n" unless alignment == 0 end - # Return the offset from $sp at which the nth (0-based) argument is + # Return the offset from the frame base at which the nth argument is # stored. def arg_offset n - @frame_size + n * @WORDSIZE + n * @WORDSIZE end # Return an $sp-relative reference for the nth (0-based) argument def arg_reference n - "#{arg_offset n}($sp)" + offset_reference(arg_offset(n)) end # Return the register in which the nth (0-based) argument is stored, or @@ -197,9 +197,9 @@ module Voodoo raise "Cannot begin function when already in a function" end - emit "# function #{formals.join ' '}\n" environment = Environment.new @environment - environment.add_args formals + @frame_size = 0 + formals.each {|x| environment.add_arg x, arg_offset(environment.args)} @environment = environment @function_end_label = gensym emit_function_prologue formals, nlocals @@ -334,7 +334,8 @@ module Voodoo # Save parameters 0 .. 3 in the stack space that the caller # should have allocated for them. [@NREGISTER_ARGS, formals.length].min.times do |n| - emit "sw $#{n + @REGISTER_ARG_BASE}, #{n * @WORDSIZE}($29)\n" + ref = offset_reference(@environment[formals[n]]) + emit "sw $#{n + @REGISTER_ARG_BASE}, #{ref}\n" end create_frame nlocals @@ -577,47 +578,35 @@ module Voodoo emit "#{name}:\n" end - # Introduce a new local variable + # Introduces a new local variable. def let symbol, *expr emit "# let #{symbol} #{expr.join ' '}\n" n = @environment.locals - @environment.add_local symbol - - # Extend stack frame, if necessary. - # This should never be necessary, because we allocate enough - # space in the top-level function or block. - if @environment.locals > max_locals - $stderr.puts "WARNING: Stack frame too small. Possible BUG" - $stderr.puts "Frame size #{@frame_size}, max locals #{max_locals}" + - ", actual locals #{@environment.locals}" - # Extend frame by 8 bytes, to keep $sp a multiple of 8 - emit "addiu $sp, $sp, -8\n" - @frame_size = @frame_size + 8 - end - register = local_register n ref = local_reference n if register # We will use a register to store the value + @environment.add_local symbol, register # Save current value of register emit "sw #{register}, #{ref}\n" # Set new value eval_expr expr, register else # We will use the stack to store the value + @environment.add_local symbol, local_offset(n) eval_expr expr, @TEMPORARY emit "sw #{@TEMPORARY}, #{ref}\n" end end - # Load the value at the given address. + # Loads the value at the given address. def load_at address, register = @TEMPORARY load_value_into_register address, register emit "lw #{register}, 0(#{register})\n" register end - # Load a value into a register. + # Loads a value into a register. # Returns the name of the register. # If the value was already in a register, the name of that # register is returned. @@ -638,22 +627,13 @@ module Voodoo end elsif symbol? x binding = @environment[x] - if binding - case binding[0] - when :arg - emit "lw #{register}, #{arg_reference binding[1]}\n" - return register - when :local - n = binding[1] - if register_local? n - return local_register(n) - else - emit "lw #{register}, #{local_reference n}\n" - return register - end - else - raise "Don't know how to load #{x.inspect}" - end + if binding.kind_of? String + # Value is already in a register. Return register name. + return binding + elsif binding.kind_of? Integer + # Load value from memory. + emit "lw #{register}, #{offset_reference binding}\n" + return register else # Assume global emit "lui #{register}, %hi(#{x})\n" @@ -675,16 +655,16 @@ module Voodoo end end - # Return the offset from $sp at which the nth (0-based) local variable is - # stored. For register locals this is the offset at which the saved + # Return the offset from the frame base at which the nth local is stored. + # For register locals this is the offset at which the saved # value (from the calling function) is stored. def local_offset n - @frame_size - @INITIAL_FRAME_SIZE - (n + 1) * @WORDSIZE + -(n + 3) * @WORDSIZE end # Return an $sp-relative reference for the nth (0-based) local def local_reference n - "#{local_offset n}($sp)" + offset_reference(local_offset(n)) end # Return the register in which the nth local (0-based) is stored, or @@ -709,6 +689,12 @@ module Voodoo [0, n - @NREGISTER_ARGS].max end + # Given an offset relative to the base of the frame, returns + # an reference to that memory location. + def offset_reference offset + "#{offset + @frame_size}($sp)" + end + # Returns true if the nth (0-based) argument is stored in a register def register_arg? n n < @NREGISTER_ARGS @@ -733,33 +719,22 @@ module Voodoo # Set a variable to the result of evaluating an expression def set symbol, *expr - emit "# set #{symbol} #{expr.join ' '}\n" - - x = @environment[symbol] - if x == nil - raise "Cannot change value of constant #{symbol}" - end - - if x[0] == :local - register = local_register x[1] - else - register = nil - end - - if register - # Set new value - eval_expr expr, register + if at_expr? symbol + eval_expr expr, @RETURN + load_value_into_register symbol.to_s[1..-1].to_sym, @TEMPORARY + emit "sw #{@RETURN}, 0(#{@TEMPORARY})\n" else - case x[0] - when :local - ref = local_reference x[1] - when :arg - ref = arg_reference x[1] + x = @environment[symbol] + if x == nil + raise "Cannot change value of constant #{symbol}" + elsif x.kind_of? String + # Register + eval_expr expr, x else - raise "??? #{sym} is neither a local nor an argument" + # Should be an integer. + eval_expr expr, @TEMPORARY + emit "sw #{@TEMPORARY}, #{offset_reference x}\n" end - eval_expr expr, @TEMPORARY - emit "sw #{@TEMPORARY}, #{ref}\n" end end -- 2.11.4.GIT