Browse Source

[PATCH 098/188] adding support for getting a function reference via
i32.const

From 397839c0f398ee3ac019a0a1d11fc435bd42c851 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Mon, 16 Mar 2020 17:03:00 -0400

git-svn-id: branches/wasm@46094 -

nickysn 5 years ago
parent
commit
01151eb899

+ 14 - 10
utils/wasmbin/wasmbincode.pas

@@ -206,15 +206,19 @@ const
 
 
 type
 type
   TInstParamType = (ipNone,
   TInstParamType = (ipNone,
-    ipLeb,   // label index or function index
-    ip2Leb,  // memory arguments, ask for offset + align
-    ipi32,     // signed Leb of maximum 4 bytes
-    ipi64,     // signed Leb of maximum 8 bytes
-    ipf32,     // float point single
-    ipf64,     // float point double
-    ipTable,   // a complex structure... used for br_table only
-    ipResType, // result type used for blocks, such as If, block or loop
-    ipCallType // used for call_indirect
+    ipLeb,      // label index or function index
+    ip2Leb,     // memory arguments, ask for offset + align
+    ipi32,      // signed Leb of maximum 4 bytes
+    ipi64,      // signed Leb of maximum 8 bytes
+    ipf32,      // float point single
+    ipf64,      // float point double
+    ipTable,    // a complex structure... used for br_table only
+    ipResType,  // result type used for blocks, such as If, block or loop
+    ipCallType, // used for call_indirect
+    ipi32OrFunc // use for i32.const. Either a numeric OR function id is accepted.
+                // numeric is used as an actually value.
+                // function Id will be replaced with a reference number to the function
+                // and relocation information would be generated
   );
   );
   TInstFlag = record
   TInstFlag = record
     valid : Boolean;
     valid : Boolean;
@@ -288,7 +292,7 @@ const
    ,(valid: true;  Param: ip2Leb)     // 3E  i64_store32
    ,(valid: true;  Param: ip2Leb)     // 3E  i64_store32
    ,(valid: true;  Param: ipNone)     // 3F  memory_size
    ,(valid: true;  Param: ipNone)     // 3F  memory_size
    ,(valid: true;  Param: ipNone)     // 40  memory_grow
    ,(valid: true;  Param: ipNone)     // 40  memory_grow
-   ,(valid: true;  Param: ipi32)      // 41  i32_const
+   ,(valid: true;  Param: ipi32OrFunc)// 41  i32_const
    ,(valid: true;  Param: ipi64)      // 42  i64_const
    ,(valid: true;  Param: ipi64)      // 42  i64_const
    ,(valid: true;  Param: ipf32)      // 43  f32_const
    ,(valid: true;  Param: ipf32)      // 43  f32_const
    ,(valid: true;  Param: ipf64)      // 44  f64_const
    ,(valid: true;  Param: ipf64)      // 44  f64_const

+ 11 - 0
utils/wasmbin/wasmbinwriter.pas

@@ -501,6 +501,7 @@ procedure TBinWriter.WriteInstList(list: TWasmInstrList; ofsAddition: LongWord);
 var
 var
   i  : integer;
   i  : integer;
   ci : TWasmInstr;
   ci : TWasmInstr;
+  idx : integer;
 begin
 begin
   for i:=0 to list.Count-1 do begin
   for i:=0 to list.Count-1 do begin
     ci :=list[i];
     ci :=list[i];
@@ -513,6 +514,16 @@ begin
       ipi64: begin     // signed Leb of maximum 8 bytes
       ipi64: begin     // signed Leb of maximum 8 bytes
         WriteI64Operand(dst, ci.operandText);
         WriteI64Operand(dst, ci.operandText);
       end;
       end;
+
+      ipi32OrFunc: begin
+        if (ci.operandText<>'') and (ci.operandText[1]='$') then begin
+          idx := FindFunc(module, ci.operandText);
+          AddReloc(INST_RELOC_FLAGS[ci.code].relocType, dst.Position+ofsAddition, idx);
+          //todo: there's no need
+          WriteU32(dst, LongWord(idx));
+        end else
+          WriteI32Operand(dst, ci.operandText);
+      end;
       //ipf32,     // float point single
       //ipf32,     // float point single
       //ipf64,     // float point double
       //ipf64,     // float point double
 
 

+ 1 - 1
utils/wasmbin/wasmlink.pas

@@ -229,7 +229,7 @@ const
    ,(doReloc: false; relocType: $FF)  // 3F  memory_size
    ,(doReloc: false; relocType: $FF)  // 3F  memory_size
    ,(doReloc: false; relocType: $FF)  // 40  memory_grow
    ,(doReloc: false; relocType: $FF)  // 40  memory_grow
 
 
-   ,(doReloc: true;  relocType: $FF)  // 41  i32_const // TODO: special case for function address
+   ,(doReloc: true;  relocType: R_WASM_FUNCTION_INDEX_LEB)  // 41  i32_const // TODO: special case for function address
 
 
    ,(doReloc: false; relocType: $FF)  // 42  i64_const
    ,(doReloc: false; relocType: $FF)  // 42  i64_const
    ,(doReloc: false; relocType: $FF)  // 43  f32_const
    ,(doReloc: false; relocType: $FF)  // 43  f32_const

+ 2 - 0
utils/wasmbin/wasmmodule.pas

@@ -183,6 +183,8 @@ procedure Normalize(m: TWasmModule);
 function WasmBasTypeToChar(b: byte): Char;
 function WasmBasTypeToChar(b: byte): Char;
 function WasmFuncTypeDescr(t: TWasmFuncType): string;
 function WasmFuncTypeDescr(t: TWasmFuncType): string;
 
 
+function FindFunc(m: TWasmModule; const funcIdx: string): integer;
+
 implementation
 implementation
 
 
 // returing a basic wasm basic type to a character
 // returing a basic wasm basic type to a character

+ 5 - 2
utils/wasmbin/watparser.pas

@@ -231,15 +231,18 @@ begin
   while sc.token=weInstr do begin
   while sc.token=weInstr do begin
     ci := dst.AddInstr(sc.instrCode);
     ci := dst.AddInstr(sc.instrCode);
     sc.Next;
     sc.Next;
+
     case INST_FLAGS[ci.code].Param of
     case INST_FLAGS[ci.code].Param of
       ipNone:; // do nothing
       ipNone:; // do nothing
 
 
       ipLeb:
       ipLeb:
         ParseNumOrIdx(sc, ci.operandNum, ci.operandIdx);
         ParseNumOrIdx(sc, ci.operandNum, ci.operandIdx);
 
 
-      ipi32,ipi64,ipf32,ipf64:
+      ipi32,ipi64,ipf32,ipf64,ipi32OrFunc:
       begin
       begin
-        if sc.token<>weNumber then
+        if (INST_FLAGS[ci.code].Param = ipi32OrFunc) and (sc.token = weIdent) then
+          ci.operandText := sc.resText
+        else if sc.token<>weNumber then
           ErrorExpectButFound(sc, 'number');
           ErrorExpectButFound(sc, 'number');
         ci.operandText := sc.resText;
         ci.operandText := sc.resText;
         sc.Next;
         sc.Next;