From 301267d90f9e7deb8ef884270dbae1c6a7fa1c23 Mon Sep 17 00:00:00 2001 From: inglorion Date: Sun, 17 Feb 2013 13:26:11 +0100 Subject: [PATCH] shared libraries can now export variables on MIPS --- lib/voodoo/generators/common_code_generator.rb | 19 ++++++++++++++++ lib/voodoo/generators/mips_gas_generator.rb | 30 +++++++++++++++----------- test/Makefile | 11 ++++++---- test/libvar.voo | 18 ++++++++++++++++ test/test | 2 ++ test/var.voo | 21 ++++++++++++++++++ 6 files changed, 84 insertions(+), 17 deletions(-) create mode 100644 test/libvar.voo create mode 100644 test/var.voo diff --git a/lib/voodoo/generators/common_code_generator.rb b/lib/voodoo/generators/common_code_generator.rb index d94bdd0..d804750 100644 --- a/lib/voodoo/generators/common_code_generator.rb +++ b/lib/voodoo/generators/common_code_generator.rb @@ -1,3 +1,5 @@ +require 'set' + module Voodoo # Common base class for code generators. # @@ -44,6 +46,7 @@ module Voodoo @environment = @top_level @output_file_suffix = '.o' @open_labels = [] # Labels for which we must emit size annotations + @relocated_symbols = Set.new @features = { :voodoo => "1.1" # Voodoo language version } @@ -293,6 +296,14 @@ module Voodoo comment code.join(' ') end + # Declares that the given symbols are to be externally visible. + def export *symbols + if real_section_name(section) == ".data" + @relocated_symbols.merge symbols + end + emit_export *symbols + end + # Adds a function to the current section. def function formals, *code nlocals = count_locals code @@ -306,6 +317,14 @@ module Voodoo symbol?(symbol) && @environment[symbol] == nil end + # Declares that the given symbols are imported from an external object. + def import *symbols + if real_section_name(section) == ".data" + @relocated_symbols.merge symbols + end + emit_import *symbols + end + # Executes a block of code using the given section as the current section. def in_section name, &block oldsection = @section diff --git a/lib/voodoo/generators/mips_gas_generator.rb b/lib/voodoo/generators/mips_gas_generator.rb index 34d0025..dd6afdc 100644 --- a/lib/voodoo/generators/mips_gas_generator.rb +++ b/lib/voodoo/generators/mips_gas_generator.rb @@ -360,6 +360,11 @@ module Voodoo emit ".align #{alignment}\n" end + # Exports symbols from the current section. + def emit_export *symbols + symbols.each { |sym| emit ".globl #{sym}\n" } + end + # Emits function prologue. def emit_function_prologue formals = [], nlocals = 0 # Calculate new value for $gp @@ -389,6 +394,12 @@ module Voodoo end end + # Imports labels into the current section. + def emit_import *symbols + # Record imported labels in @imports + symbols.each { |sym| @imports[sym] = sym } + end + # Emits a label type annotation. def emit_label_type name, type type_map = { @@ -530,11 +541,6 @@ module Voodoo end end - # Exports symbols from the current section. - def export *symbols - symbols.each { |sym| emit ".globl #{sym}\n" } - end - # Loads byte from _base_ + _offset_ into _register_. def get_byte base, offset, register # If base is an integer, but offset isn't, swap them @@ -626,12 +632,6 @@ module Voodoo common_if :ifne, x, y end - # Imports labels into the current section. - def import *symbols - # Record imported labels in @imports - symbols.each { |sym| @imports[sym] = sym } - end - # Introduces a new local variable. def let symbol, *expr n = @environment.locals @@ -688,8 +688,12 @@ module Voodoo return register else # Assume global - emit "lui #{register}, %hi(#{x})\n" - emit "addiu #{register}, %lo(#{x})\n" + if @relocated_symbols.include? x + emit "lw #{register}, %got(#{x})(#{@GOT})\n" + else + emit "lui #{register}, %hi(#{x})\n" + emit "addiu #{register}, %lo(#{x})\n" + end return register end elsif at_expr? x diff --git a/test/Makefile b/test/Makefile index f43a13b..482ccda 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,10 +4,10 @@ NASM ?= nasm VOODOOC ?= env RUBYLIB=$(PWD)/../lib:$(RUBYLIB) ../bin/voodooc TARGETS = auto-bytes auto-words at block bitwise bytes call div else-if fact \ - func goto hello if libfunc.so many-args many-args-tail many-locals \ - mod mul plusminus \ - raw restore-frame restore-locals rotate save-frame-and-locals \ - set-at set-byte set-word shift substitute-number tail-calls vtable gcd + func goto hello if libfunc.so libvar.so many-args many-args-tail \ + many-locals mod mul plusminus raw restore-frame restore-locals \ + rotate save-frame-and-locals set-at set-byte set-word shift \ + substitute-number tail-calls var vtable gcd all : $(TARGETS) @@ -26,6 +26,9 @@ test : $(TARGETS) gcd.o : gcd.rb env RUBYLIB=$(PWD)/../lib:$(RUBYLIB) $(RUBY) gcd.rb +var : var.o libvar.so + $(CC) var.o -o var -L. -lvar + .SUFFIXES : .asm .o .s .so .voo .asm.o : diff --git a/test/libvar.voo b/test/libvar.voo new file mode 100644 index 0000000..f696e0c --- /dev/null +++ b/test/libvar.voo @@ -0,0 +1,18 @@ +# Shared library exporting a variable. + +section data +export foo + +align +foo: +word 42 + + +section functions +export add_foo + +align +add_foo: +function x + return add x @foo +end function diff --git a/test/test b/test/test index 2899f96..e7fde63 100755 --- a/test/test +++ b/test/test @@ -89,6 +89,8 @@ add_test1 'set-word' add_test1 'shift' +add_test 'var', 'LD_LIBRARY_PATH=$PWD ./var', "18 + 9 = 27\n" + add_test1 'vtable' add_test1 'gcd' diff --git a/test/var.voo b/test/var.voo new file mode 100644 index 0000000..08a6d95 --- /dev/null +++ b/test/var.voo @@ -0,0 +1,21 @@ +# Test using a variable from a shared library. + +section data +import foo + +format: +string "%d + %d = %d\n\x00" + +section functions +import add_foo printf +export main + +align +main: +function argc argv + let x 18 + set @foo 9 + let z call add_foo x + call printf format x @foo z + return 0 +end function -- 2.11.4.GIT