Browse Source

[PATCH 63/83] adding support for stack variables and wasm-C-abi

From 927dd8faefacf3b4d3ac8d1f29d60abe6fd4c595 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Tue, 8 Oct 2019 17:19:37 -0400

git-svn-id: branches/wasm@45940 -
nickysn 5 years ago
parent
commit
0b08e0a4c0
4 changed files with 49 additions and 23 deletions
  1. 5 3
      compiler/wasm/aasmcpu.pas
  2. 13 0
      compiler/wasm/agwat.pas
  3. 28 18
      compiler/wasm/hlcgcpu.pas
  4. 3 2
      compiler/wasm/tgcpu.pas

+ 5 - 3
compiler/wasm/aasmcpu.pas

@@ -101,7 +101,8 @@ uses
 
       tai_local = class(tai)
         bastyp: TWasmBasicType;
-        constructor create(abasictype: TWasmBasicType);
+        name : string;
+        constructor create(abasictype: TWasmBasicType; const aname: string = '');
       end;
 
     procedure InitAsm;
@@ -114,11 +115,12 @@ implementation
 
     { tai_local }
 
-    constructor tai_local.create(abasictype: TWasmBasicType);
+    constructor tai_local.create(abasictype: TWasmBasicType; const aname: string);
       begin
+        inherited Create;
         bastyp := abasictype;
         typ := ait_local;
-        inherited Create;
+        name := aname;
       end;
 
     { timpexp_ai }

+ 13 - 0
compiler/wasm/agwat.pas

@@ -576,6 +576,12 @@ implementation
              ait_local :
                begin
                  writer.AsmWrite(#9'(local ');
+                 if tai_local(hp).name <> '' then
+                   begin
+                     writer.AsmWrite(' ');
+                     writer.AsmWrite(tai_local(hp).name);
+                     writer.AsmWrite(' ');
+                   end;
                  writer.AsmWrite( WasmBasicTypeStr[ tai_local(hp).bastyp ] );
                  writer.AsmWrite(')');
                  writer.AsmLn;
@@ -603,6 +609,13 @@ implementation
 
         { print all global variables }
         //current_asmdata.AsmSymbolDict
+        if current_module.islibrary then
+          begin
+            writer.AsmWrite(#9'(global $__stack_top (mut i32) (i32.const ');
+            writer.AsmWrite(tostr(globals.stacksize));
+            writer.AsmWriteLn('))');
+          end;
+
         WriteSymtableVarSyms(current_module.globalsymtable);
         WriteSymtableVarSyms(current_module.localsymtable);
 

+ 28 - 18
compiler/wasm/hlcgcpu.pas

@@ -1021,20 +1021,15 @@ implementation
         exit;
 
       // setting up memory offset
-      if assigned(ref.symbol) then
-        list.Concat(taicpu.op_sym(a_get_global, ref.symbol))
-      else if ref.index <> NR_NO then // array access
+      if assigned(ref.symbol) then begin
+        list.Concat(taicpu.op_sym(a_get_global, ref.symbol));
+      end else if ref.index <> NR_NO then // array access
       begin
         // it's just faster to sum two of those together
         list.Concat(taicpu.op_reg(a_get_local, ref.base));
         list.Concat(taicpu.op_reg(a_get_local, ref.index));
         list.Concat(taicpu.op_none(a_i32_add));
-        exit;
-      end
-      else
-        list.Concat(taicpu.op_const(a_i32_const, 0)); //todo: this should not be 0, this should be reference to a global "memory"
-
-        if (ref.base<>NR_NO) then
+      end else if (ref.base<>NR_NO) then
           begin
             if (ref.base<>NR_STACK_POINTER_REG) then
               begin
@@ -1050,12 +1045,9 @@ implementation
                 { field name/type encoded in symbol, no index/offset }
                 result:=1;
               end
-            else
+            else // if (ref.base = NR_FRAME_POINTER_REG) then
               begin
-                { local variable -> offset encoded in opcode and nothing to
-                  do here, except for checking that it's a valid reference }
-                if assigned(ref.symbol) then
-                  internalerror(2010120523);
+                list.Concat(taicpu.op_sym(a_get_local, current_asmdata.RefAsmSymbol('fp',AT_ADDR) ));
               end;
           end
         else
@@ -1618,16 +1610,34 @@ implementation
     begin
       { the localsize is based on tg.lasttemp -> already in terms of stack
         slots rather than bytes }
-      list.concat(tai_directive.Create(asd_jlimit,'locals '+tostr(localsize)));
+      //list.concat(tai_directive.Create(asd_jlimit,'locals '+tostr(localsize)));
       { we insert the unit initialisation code afterwards in the proginit code,
         and it uses one stack slot }
-      if (current_procinfo.procdef.proctypeoption=potype_proginit) then
-        fmaxevalstackheight:=max(1,fmaxevalstackheight);
-      list.concat(tai_directive.Create(asd_jlimit,'stack '+tostr(fmaxevalstackheight)));
+      //if (current_procinfo.procdef.proctypeoption=potype_proginit) then
+        //fmaxevalstackheight:=max(1,fmaxevalstackheight);
+      list.Concat(tai_local.create(wbt_i32, '$fp')); //TWasmBasicType
+      list.Concat(tai_local.create(wbt_i32, '$bp')); //TWasmBasicType
+
+      list.Concat(taicpu.op_sym(a_get_global , current_asmdata.RefAsmSymbol('__stack_top',AT_LABEL)));
+      list.Concat(taicpu.op_sym(a_set_local, current_asmdata.RefAsmSymbol('bp',AT_LABEL)));
+
+      if (localsize>0) then begin
+        list.Concat(taicpu.op_sym(a_get_local, current_asmdata.RefAsmSymbol('bp',AT_LABEL)));
+        list.concat(taicpu.op_const(a_i32_const, localsize ));
+        list.concat(taicpu.op_none(a_i32_sub));
+        list.Concat(taicpu.op_sym(a_set_local, current_asmdata.RefAsmSymbol('fp',AT_LABEL)));
+        list.Concat(taicpu.op_sym(a_get_local, current_asmdata.RefAsmSymbol('fp',AT_LABEL)));
+        list.Concat(taicpu.op_sym(a_set_global, current_asmdata.RefAsmSymbol('__stack_top',AT_LABEL)));
+      end;
+
+      //list.concat(tai_directive.Create(asd_jlimit,'stack '+tostr(fmaxevalstackheight)));
     end;
 
   procedure thlcgwasm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
     begin
+      list.Concat(taicpu.op_sym(a_get_local, current_asmdata.RefAsmSymbol('bp',AT_LABEL)));
+      list.Concat(taicpu.op_sym(a_set_global , current_asmdata.RefAsmSymbol('__stack_top',AT_LABEL)));
+
       list.concat(taicpu.op_none(a_return));
     end;
 

+ 3 - 2
compiler/wasm/tgcpu.pas

@@ -313,7 +313,8 @@ unit tgcpu;
 
     procedure ttgwasm.alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference);
       begin
-        Internalerror(2019091802);
+        inherited;
+        //Internalerror(2019091802);
         { the WebAssembly only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
           FPC) temps on the stack. double and int64 are 2 slots, the rest is one slot.
           There are no problems with reusing the same slot for a value of a different
@@ -360,7 +361,7 @@ unit tgcpu;
         if defToWasmBasic(def, wbt) then
           alloclocalVarToRef(wbt, ref)
         else begin
-          Internalerror(2019091801); // no support of structural type
+          //Internalerror(2019091801); // no support of structural type
           inherited;
         end;
       end;