Browse Source

[PATCH 101/188] initial elements support

From 4f81759337d5e50b9d4d080612af2d08c4c0d889 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Tue, 17 Mar 2020 15:01:33 -0400

git-svn-id: branches/wasm@46097 -
nickysn 5 years ago
parent
commit
caa77c3b74
1 changed files with 138 additions and 2 deletions
  1. 138 2
      utils/wasmbin/wasmmodule.pas

+ 138 - 2
utils/wasmbin/wasmmodule.pas

@@ -3,7 +3,7 @@ unit wasmmodule;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, wasmbin, wasmbincode;
+  Classes, SysUtils, wasmbin, wasmbincode, wasmlink;
 
 
 type
 type
   TLinkBind = (lbUndefined = 0
   TLinkBind = (lbUndefined = 0
@@ -70,10 +70,15 @@ type
     operandIdx  : string;
     operandIdx  : string;
     operandNum  : integer;    // for call_indirect this is table index
     operandNum  : integer;    // for call_indirect this is table index
     operandText : string;
     operandText : string;
-    insttype : TWasmFuncType; // used by call_indirect only
+    insttype    : TWasmFuncType; // used by call_indirect only
+
+    hasRelocIdx : Boolean;
+    relocIdx    : integer;
+    relocType   : Byte;
     function addInstType: TWasmFuncType;
     function addInstType: TWasmFuncType;
     constructor Create;
     constructor Create;
     destructor Destroy; override;
     destructor Destroy; override;
+    procedure SetReloc(ARelocType: byte; ARelocIndex: Integer);
   end;
   end;
 
 
   { TWasmInstrList }
   { TWasmInstrList }
@@ -110,6 +115,17 @@ type
     function LocalsCount: integer;
     function LocalsCount: integer;
   end;
   end;
 
 
+  { TWasmElement }
+
+  TWasmElement = class(TObject)
+    tableIdx  : Integer;
+    offset    : Integer;
+    funcCount : Integer;
+    funcs     : array of LongWord;
+    function AddFunc(idx: integer): integer;
+    constructor Create;
+  end;
+
   { TWasmExport }
   { TWasmExport }
 
 
   TWasmExport = class(TObject)
   TWasmExport = class(TObject)
@@ -155,6 +171,7 @@ type
     funcs   : TList;
     funcs   : TList;
     exp     : TList;
     exp     : TList;
     tables  : TList;
     tables  : TList;
+    elems   : TList;
   public
   public
     constructor Create;
     constructor Create;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -178,6 +195,10 @@ type
     function AddExport: TWasmExport;
     function AddExport: TWasmExport;
     function GetExport(i: integer): TWasmExport;
     function GetExport(i: integer): TWasmExport;
     function ExportCount: integer;
     function ExportCount: integer;
+
+    function AddElement: TWasmElement;
+    function GetElement(i: integer): TWasmElement;
+    function ElementCount: Integer;
   end;
   end;
 
 
 // making binary friendly. finding proper "nums" for each symbol "index"
 // making binary friendly. finding proper "nums" for each symbol "index"
@@ -187,6 +208,9 @@ function WasmBasTypeToChar(b: byte): Char;
 function WasmFuncTypeDescr(t: TWasmFuncType): string;
 function WasmFuncTypeDescr(t: TWasmFuncType): string;
 
 
 function FindFunc(m: TWasmModule; const funcIdx: string): integer;
 function FindFunc(m: TWasmModule; const funcIdx: string): integer;
+// tries to register a function in the module
+function RegisterFuncIdxInElem(m: TWasmModule; const func: Integer): integer;
+function RegisterFuncInElem(m: TWasmModule; const funcId: string): integer;
 
 
 implementation
 implementation
 
 
@@ -249,6 +273,24 @@ begin
   l.Clear;
   l.Clear;
 end;
 end;
 
 
+{ TWasmElement }
+
+function TWasmElement.AddFunc(idx: integer): Integer;
+begin
+  if funcCount = length(funcs) then begin
+    if funcCount=0 then SetLength(funcs, 4)
+    else SetLength(funcs, funcCount*2);
+  end;
+  Result:=funcCount;
+  funcs[funcCount]:=idx;
+  inc(funcCount);
+end;
+
+constructor TWasmElement.Create;
+begin
+  offset:=-1;
+end;
+
 { TWasmImport }
 { TWasmImport }
 
 
 function TWasmImport.AddFunc: TWasmFunc;
 function TWasmImport.AddFunc: TWasmFunc;
@@ -291,6 +333,13 @@ begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
+procedure TWasmInstr.SetReloc(ARelocType: byte; ARelocIndex: Integer);
+begin
+  hasRelocIdx := true;
+  relocType := ARelocType;
+  relocIdx := ARelocIndex;
+end;
+
 { TWasmInstrList }
 { TWasmInstrList }
 
 
 function TWasmInstrList.GetItem(i: integer): TWasmInstr;
 function TWasmInstrList.GetItem(i: integer): TWasmInstr;
@@ -425,10 +474,13 @@ begin
   exp := TList.Create;
   exp := TList.Create;
   imports := TList.Create;
   imports := TList.Create;
   tables := TList.Create;
   tables := TList.Create;
+  elems := TList.Create;
 end;
 end;
 
 
 destructor TWasmModule.Destroy;
 destructor TWasmModule.Destroy;
 begin
 begin
+  ClearList(elems);
+  elems.Free;
   ClearList(tables);
   ClearList(tables);
   tables.Free;
   tables.Free;
   ClearList(imports);
   ClearList(imports);
@@ -537,6 +589,25 @@ begin
   Result:=exp.Count;
   Result:=exp.Count;
 end;
 end;
 
 
+function TWasmModule.AddElement: TWasmElement;
+begin
+  Result:=TWasmElement.Create;
+  elems.add(Result);
+end;
+
+function TWasmModule.GetElement(i: integer): TWasmElement;
+begin
+  if (i>=0) and (i<elems.Count) then
+    Result:=TWasmElement(elems[i])
+  else
+    Result:=nil;
+end;
+
+function TWasmModule.ElementCount: Integer;
+begin
+  Result := elems.Count;
+end;
+
 { TWasmFunc }
 { TWasmFunc }
 
 
 constructor TWasmFunc.Create;
 constructor TWasmFunc.Create;
@@ -648,6 +719,31 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure PopulateRelocData(module: TWasmModule; ci: TWasmInstr);
+var
+  idx : integer;
+begin
+  case INST_FLAGS[ci.code].Param of
+    ipi32OrFunc:
+      if (ci.operandText<>'') and (ci.operandText[1]='$') then begin
+        //if not ci.hasRelocIdx then
+        idx := RegisterfuncInElem(module, ci.operandText);
+        //AddReloc(rt, dst.Position+ofsAddition, idx);
+        ci.operandNum := idx;
+        ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, idx);
+      end;
+
+    ipLeb:
+       if (INST_RELOC_FLAGS[ci.code].doReloc) then begin
+         ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, ci.operandNum);
+       end;
+
+    ipCallType:
+      if Assigned(ci.insttype) then
+        ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, ci.insttype.typeNum);
+  end;
+end;
+
 // Normalizing instruction list, popuplating index reference ($index)
 // Normalizing instruction list, popuplating index reference ($index)
 // with the actual numbers. (params, locals, globals, memory, functions index)
 // with the actual numbers. (params, locals, globals, memory, functions index)
 procedure NormalizeInst(m: TWasmModule; f: TWasmFunc; l: TWasmInstrList; checkEnd: boolean = true);
 procedure NormalizeInst(m: TWasmModule; f: TWasmFunc; l: TWasmInstrList; checkEnd: boolean = true);
@@ -683,6 +779,8 @@ begin
           ci.insttype.typeNum:=RegisterFuncType(m, ci.insttype);
           ci.insttype.typeNum:=RegisterFuncType(m, ci.insttype);
       end;
       end;
     end;
     end;
+
+    PopulateRelocData(m, ci);
   end;
   end;
 
 
   // adding end instruction
   // adding end instruction
@@ -751,4 +849,42 @@ begin
   end;
   end;
 end;
 end;
 
 
+function RegisterFuncIdxInElem(m: TWasmModule; const func: Integer): integer;
+var
+  el : TWasmElement;
+  i  : Integer;
+const
+  NON_ZEROFFSET = 1; // being compliant with Linking convention
+  // The output table elements shall begin at a non-zero offset within
+  // the table, so that a call_indirect 0 instruction is guaranteed to fail.
+  // Finally, when processing table relocations for symbols which
+  // have neither an import nor a definition (namely, weakly-undefined
+  // function symbols), the value 0 is written out as the value of the relocation.
+begin
+  if m.ElementCount=0 then begin
+    el := m.AddElement;
+    el.offset := NON_ZEROFFSET;
+  end else
+    el := m.GetElement(0);
+  Result:=-1;
+  for i:=0 to el.funcCount-1 do begin
+    if el.funcs[i] = func then
+      Result:=i;
+  end;
+  if Result<0 then
+    Result := el.AddFunc(func);
+  writeln('result=',result,' for ',func);
+end;
+
+function RegisterFuncInElem(m: TWasmModule; const funcId: string): integer;
+var
+  fnidx : integer;
+begin
+  fnidx := FindFunc(m, funcId);
+  if fnidx>=0 then
+    Result := RegisterFuncIdxInElem(m, fnidx)
+  else
+    Result := -1;
+end;
+
 end.
 end.