From 8027a76fd36d0d8a2338878a8c2a9bc0f237e49f Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 15 Nov 2023 22:26:26 -0500 Subject: [PATCH] now emitting code for param access and handling function return values --- aas.rb | 17 +++--- cerise.rb | 153 +++++++++++++++++++++++++----------------------------- 2 files changed, 82 insertions(+), 88 deletions(-) diff --git a/aas.rb b/aas.rb index 0d06a05..9c0fb4f 100755 --- a/aas.rb +++ b/aas.rb @@ -244,15 +244,16 @@ module Targets ############ # FUNCTIONS ############ - def call - emit "call #{name}" - end - - def call_and_ret + def fcall(name) emit "call #{name}" emit "pushq %rax" end +# def fcallv(name) +# emit "call #{name}" +# emit "pushq %rax" +# end + def scall num_args $syscalls[num_args] = true emit "call syscall#{num_args}" @@ -262,6 +263,7 @@ module Targets ######### # MEMORY ######### + # get_global int # set_global int # get_local int @@ -290,6 +292,9 @@ class Function ## # Function Scaffolding: Locals and Returns ## + def get_param(num) + emit "movq #{8*(num+1)}(%rbp), %rax" + end def locals(count) $asm_out.write "subq $#{count * 8}, %rsp\n" @@ -351,7 +356,7 @@ def gen_syscall_handler(n) $asm_out.write "syscall#{n}:\n" emit "movq 8(%rsp), %rax" n.times do |i| - emit "movq #{(n+1)*8}(%rsp), #{regs[i]}" + emit "movq #{(i+2)*8}(%rsp), #{regs[i]}" end emit "syscall" emit "ret $#{(n+1) * 8}" diff --git a/cerise.rb b/cerise.rb index a65c74d..836940f 100755 --- a/cerise.rb +++ b/cerise.rb @@ -106,14 +106,9 @@ class SymTable find_sym(@scopes[3..-1], name) end - def add_builtin(name, kind, type, value) - @scopes[0][name] = - Symbol.new(name, 0, kind, type, value) - end - def find_sym(scopes, name) scopes.reverse_each.detect do |scope| - scope[name] + return scope[name] end end @@ -133,21 +128,19 @@ class SymTable find_sym(@scopes, name) end + def add_builtin(name, kind, type, value) + @scopes[0][name] = + Symbol.new(name, 0, kind, type, value) + end + def add_sym(name, loc, kind, type, value) + @scopes.last[name] = + Symbol.new(name, loc, kind, type, value) + end -# def add_sym(name, loc, kind, scope = :local, type = nil, value = nil) -# self[name] = { -# loc: loc, -# kind: kind, -# scope: scope, -# type: type, -# value: nil -# } -# end -# -# def set_type(name, type) -# (self[name] || {})[:type] = type -# end + def each(&block) + @scopes.last.each(&block) + end end @@ -496,11 +489,11 @@ class Parser def initialize(path = nil) @syms = SymTable.new - syms.add_sym(:void, 0, :type, :builtin, :void) - syms.add_sym(:bool, 0, :type, :builtin, :bool) - syms.add_sym(:int, 0, :type, :builtin, :int) - syms.add_sym(:string, 0, :type, :builtin, :string) - syms.add_sym(:float, 0, :type, :builtin, :float) + syms.add_builtin(:void, 0, :type, :void) + syms.add_builtin(:bool, 0, :type, :bool) + syms.add_builtin(:int, 0, :type, :int) + syms.add_builtin(:string, 0, :type, :string) + syms.add_builtin(:float, 0, :type, :float) parse_file(path) end @@ -583,31 +576,27 @@ class Parser def toplevel imports exports - @defs = {} -# @syms = SymTable.new - while !matches(:eof) mod_def = toplevel_defintion() + if mod_def.value.is_a? IR::Const + kind = :const + elsif mod_def.value.is_a? IR::Var + kind = :var + elsif mod_def.value.is_a? IR::Func + kind = :func +# elsif mod_def.value.is_a? IR::Type +# kind = :type + else + raise "invalid toplevel definition #{mod_def.value.class}" + end -# kind = (case mod_def.value.class -# when IR::Const.class -# :const -# when IR::Var.class -# :var -# when IR::Func.class -# :func -# else -# raise "invalid toplevel definition #{mod_def.value.class}" -# end) -# @syms.add_sym( -# mod_def.name.name, -# 0, -# kind, -# :global, -# nil, -# mod_def.value) - - @defs[mod_def.name.name] = mod_def + syms.add_sym( + mod_def.name.name, + mod_def.name.loc, + kind, + mod_def.type, + mod_def.value + ) end end @@ -755,36 +744,36 @@ class Parser end module Codegen - def self.emit(v) + def self.emit(syms, v) if v.is_a? IR::Return then - emit_return(v) + emit_return(syms, v) elsif v.is_a? IR::Const then - emit_const(v) + emit_const(syms, v) elsif v.is_a? IR::Op then - emit_binop(v) + emit_binop(syms, v) elsif v.is_a? IR::Var then - emit_var(v) + emit_var(syms, v) elsif v.is_a? IR::Call then - emit_call(v) + emit_call(syms, v) else raise "code emitting of #{v.class} not implemented" end end - def self.emit_return(v) - emit(v.value) + def self.emit_return(syms, v) + emit(syms, v.value) puts " retwv" end - def self.emit_const(v) + def self.emit_const(syms, v) if v.value.is_a? Integer puts " int #{v.value}" end end - def self.emit_binop(v) - emit(v.left) - emit(v.right) + def self.emit_binop(syms, v) + emit(syms, v.left) + emit(syms, v.right) case v.op when "+" puts " addi" @@ -801,38 +790,38 @@ module Codegen end end - def self.emit_var(v) - puts " #{v.name}" + def self.emit_var(syms, v) + sym = syms[v.name] + if sym.kind == :param + puts " get_param #{sym.value}" + end end - def self.emit_call(v) + def self.emit_call(syms, v) v.args.reverse.each do |arg| - emit(arg) + emit(syms, arg) end # TODO: handle args/locals/globals if v.func.is_a? IR::Var - puts " call #{v.func.name}" + puts " fcall #{v.func.name.inspect}" else - emit(v.func) - emit " callv" + emit(syms, v.func) + puts " fcallv" end end end -#$parser = Parser.new("cerise.m") -#$parser.defs.each do |name, val| -# puts "func #{name.to_sym.inspect}, #{val.value.args.length} do" -# val.value.body.each do |stmnt| -# Codegen.emit(stmnt) -# end -# puts "end\n\n" -#end - -syms = SymTable.new -syms.add_builtin(:foo, :var, nil, nil) -syms.add_sym(:foo, :var, nil, nil) -#syms.add_param(:foo, :var, nil, nil) -#syms.add_param(:foo, :var, nil, nil) -# def add_builtin(name, kind, type, value) - -pp syms +$parser = Parser.new("cerise.m") +$parser.syms.each do |name, val| + $parser.syms.open_scope + puts "func #{name.to_sym.inspect}, #{val.value.args.length} do" + val.value.args.each_with_index do |name, idx| + $parser.syms.add_sym( + name.name, name.loc, :param, name.type, idx) + end + val.value.body.each do |stmnt| + Codegen.emit($parser.syms, stmnt) + end + puts "end\n\n" + $parser.syms.close_scope +end -- 2.52.0