]> git.mdlowis.com Git - proto/aas.git/commitdiff
now emitting code for param access and handling function return values
authorMichael D. Lowis <mike@mdlowis.com>
Thu, 16 Nov 2023 03:26:26 +0000 (22:26 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Thu, 16 Nov 2023 03:26:26 +0000 (22:26 -0500)
aas.rb
cerise.rb

diff --git a/aas.rb b/aas.rb
index 0d06a056fbd440429f2dba443173e85360cf0506..9c0fb4f086a09c8c9fb2ba125e32c9da894e048a 100755 (executable)
--- 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}"
index a65c74ddb3b2eff137244f9a63f7390b3eab36ce..836940f117db711d45395b611b819e1869f7238a 100755 (executable)
--- 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