From a7d879a485cfd133e66faa3fef2b99155d264ef8 Mon Sep 17 00:00:00 2001 From: inglorion Date: Sat, 2 Feb 2013 19:11:50 -0800 Subject: [PATCH] implemented {save,restore}-frame and {save,restore}-locals on AMD64 --- lib/voodoo/generators/amd64_nasm_generator.rb | 10 ++++- lib/voodoo/generators/nasm_generator.rb | 53 +++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/lib/voodoo/generators/amd64_nasm_generator.rb b/lib/voodoo/generators/amd64_nasm_generator.rb index ba34eca..f9ce164 100644 --- a/lib/voodoo/generators/amd64_nasm_generator.rb +++ b/lib/voodoo/generators/amd64_nasm_generator.rb @@ -1,4 +1,5 @@ require 'voodoo/generators/nasm_generator' +require 'set' module Voodoo # = AMD64 NASM Code Generator @@ -85,6 +86,7 @@ module Voodoo # Registers used to store locals @LOCAL_REGS = [:r12, :r13, :r14, :r15] @NLOCAL_REGS = @LOCAL_REGS.length + @LOCAL_REGISTERS_SET = Set.new @LOCAL_REGS # Accumulator index @AX = :rax # Base index @@ -97,7 +99,11 @@ module Voodoo @BP = :rbp # Stack pointer @SP = :rsp - @SAVE_FRAME_REGISTERS = [:rbx, :r12, :r13, :r14, :r15, :rsp, :rbp] + @SAVED_FRAME_LAYOUT = { + :rbx => 0, :r12 => 1, :r13 => 2, :r14 => 3, :r15 => 4, + :rsp => 5, :rbp => 6, + } + @SAVE_FRAME_REGISTERS = @SAVED_FRAME_LAYOUT.keys super params @features.merge! \ :'bits-per-word' => '64', @@ -306,7 +312,7 @@ module Voodoo if n < @NLOCAL_REGS @LOCAL_REGS[n] else - (n - @NLOCAL_REGS + number_of_register_arguments + 1) * -@WORDSIZE + (n + number_of_register_arguments + 1) * -@WORDSIZE end end diff --git a/lib/voodoo/generators/nasm_generator.rb b/lib/voodoo/generators/nasm_generator.rb index 75518cb..64964d3 100644 --- a/lib/voodoo/generators/nasm_generator.rb +++ b/lib/voodoo/generators/nasm_generator.rb @@ -235,25 +235,62 @@ module Voodoo # Saving and restoring frames. # + # Given some local variable names, returns the registers those variables + # are stored in. If no variable names are given, returns all registers + # used to store local variables. + def registers_for_locals locals = [] + locals = @environment.symbols.keys if locals.empty? + registers = [] + locals.each do |sym| + reg = @environment[sym] + registers << reg if @LOCAL_REGISTERS_SET.include? @environment[sym] + end + registers + end + # Restores the frame saved at the given location. - def restore_frame location - load_value_into_register location, @SCRATCH_REG - @SAVE_FRAME_REGISTERS.each_with_index do |register,i| + def restore_frame frame + restore_registers_from_frame frame, @SAVE_FRAME_REGISTERS + end + + # Restores local variables from a saved frame. + def restore_locals frame, *locals + restore_registers_from_frame frame, registers_for_locals(locals) + end + + # Helper function for restore_frame and restore_locals. + def restore_registers_from_frame frame, registers + load_value_into_register frame, @SCRATCH_REG + registers.each do |register| + i = @SAVED_FRAME_LAYOUT[register] emit "mov #{register}, [#{@SCRATCH_REG} + #{i} * #{@WORDSIZE}]\n" end end # Saves the current frame to the given location. - def save_frame location - load_value_into_register location, @SCRATCH_REG - @SAVE_FRAME_REGISTERS.each_with_index do |register,i| + def save_frame frame + save_registers_to_frame frame, @SAVE_FRAME_REGISTERS + end + + # Saves local variables to the given frame. + # If no locals are specified, saves all locals. + # If locals are specified, saves only the specified ones. + def save_locals frame, *locals + save_registers_to_frame frame, registers_for_locals(locals) + end + + # Helper function for save_frame and save_locals. + def save_registers_to_frame frame, registers + load_value_into_register frame, @SCRATCH_REG + registers.each do |register| + i = @SAVED_FRAME_LAYOUT[register] emit "mov [#{@SCRATCH_REG} + #{i} * #{@WORDSIZE}], #{register}\n" end end - + # Returns the number of bytes necessary to save the current frame. def saved_frame_size - @SAVE_FRAME_REGISTERS.length * @WORDSIZE + @SAVED_FRAME_LAYOUT.length * @WORDSIZE end # -- 2.11.4.GIT