From 080aa1ca74eb92fc91e748001467325a64e09eb4 Mon Sep 17 00:00:00 2001
From: nickysn <nickysn@gmail.com>
Date: Wed, 5 Aug 2020 15:36:08 +0000
Subject: [PATCH] + added target WASI, clone of the 'WASM' target

git-svn-id: branches/wasm@46259 -
---
 .gitattributes              |   2 +
 compiler/systems.inc        |   6 +-
 compiler/systems.pas        |   2 +-
 compiler/systems/i_wasi.pas | 115 ++++++++++++++++++++++
 compiler/systems/t_wasi.pas | 187 ++++++++++++++++++++++++++++++++++++
 compiler/wasm32/cputarg.pas |   1 +
 6 files changed, 310 insertions(+), 3 deletions(-)
 create mode 100644 compiler/systems/i_wasi.pas
 create mode 100644 compiler/systems/t_wasi.pas

diff --git a/.gitattributes b/.gitattributes
index 082b0561ee..5b1dd90e9b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -874,6 +874,7 @@ compiler/systems/i_os2.pas svneol=native#text/plain
 compiler/systems/i_palmos.pas svneol=native#text/plain
 compiler/systems/i_sunos.pas svneol=native#text/plain
 compiler/systems/i_symbian.pas svneol=native#text/plain
+compiler/systems/i_wasi.pas svneol=native#text/plain
 compiler/systems/i_wasm.pas svneol=native#text/plain
 compiler/systems/i_watcom.pas svneol=native#text/plain
 compiler/systems/i_wdosx.pas svneol=native#text/plain
@@ -910,6 +911,7 @@ compiler/systems/t_os2.pas svneol=native#text/plain
 compiler/systems/t_palmos.pas svneol=native#text/plain
 compiler/systems/t_sunos.pas svneol=native#text/plain
 compiler/systems/t_symbian.pas svneol=native#text/plain
+compiler/systems/t_wasi.pas svneol=native#text/plain
 compiler/systems/t_wasm.pas svneol=native#text/plain
 compiler/systems/t_watcom.pas svneol=native#text/plain
 compiler/systems/t_wdosx.pas svneol=native#text/plain
diff --git a/compiler/systems.inc b/compiler/systems.inc
index 7ebde09094..7741e5187d 100644
--- a/compiler/systems.inc
+++ b/compiler/systems.inc
@@ -201,7 +201,8 @@
              system_z80_zxspectrum,     { 109 }
              system_z80_msxdos,         { 110 }
              system_aarch64_darwin,     { 111 }
-             system_z80_amstradcpc      { 112 }
+             system_z80_amstradcpc,     { 112 }
+             system_wasm32_wasi         { 113 }
        );
 
      type
@@ -307,7 +308,8 @@
              ld_freertos,
              ld_zxspectrum,
              ld_msxdos,
-             ld_amstradcpc
+             ld_amstradcpc,
+             ld_wasi
        );
 
        tar = (ar_none
diff --git a/compiler/systems.pas b/compiler/systems.pas
index 5c0ef74f23..3b0bfc861a 100644
--- a/compiler/systems.pas
+++ b/compiler/systems.pas
@@ -1138,7 +1138,7 @@ begin
 {$endif aarch64}
 
 {$ifdef wasm32}
-  default_target(system_wasm32_wasm);
+  default_target(system_wasm32_wasi);
 {$endif wasm32}
 
 {$ifdef z80}
diff --git a/compiler/systems/i_wasi.pas b/compiler/systems/i_wasi.pas
new file mode 100644
index 0000000000..22ef953bca
--- /dev/null
+++ b/compiler/systems/i_wasi.pas
@@ -0,0 +1,115 @@
+{
+    Copyright (c) 2019 by Dmitry Boyarintsev
+
+    This unit implements support information structures for WebAssembly
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+
+unit i_wasi;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       systems,rescmn;
+
+    const
+       res_wasmraw_info : tresinfo =
+           (
+             id     : res_none; // todo: not implemented. but could be as memory
+             resbin : 'fpcwasmres';
+             rescmd : '-o $OBJ $DBG';
+             rcbin  : '';
+             rccmd  : '';
+             resourcefileclass : nil;
+             resflags : [res_no_compile];
+           );
+
+        system_wasi_info : tsysteminfo =
+          (
+            system       : system_wasm32_wasi;
+            name         : 'WebAssembly';
+            shortname    : 'Wasm';
+            flags        : [tf_files_case_sensitive,tf_no_generic_stackcheck,
+                            { avoid the creation of threadvar tables }
+                            tf_section_threadvars];
+            cpu          : cpu_wasm32;
+            unit_env     : '';
+            extradefines : '';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.wat';
+            objext       : '.o';
+            resext       : '';
+            resobjext    : '.o';
+            sharedlibext : ''; // keep it empty! The sharedlibext drives the export module name
+                               // if this is populated, then the name should be cleared when generating import
+            staticlibext : '.a';
+            staticlibprefix : '';
+            sharedlibprefix : '';
+            sharedClibext : '.wasm';
+            staticClibext : '.wasm';
+            staticClibprefix : '';
+            sharedClibprefix : '';
+            importlibprefix : '';
+            importlibext : '.wasm';
+            Cprefix      : '';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_wasm_wabt;
+            assemextern  : as_wasm_binaryen;
+            link         : ld_wasi;
+            linkextern   : ld_wasi; // there's no linker, only object files for WASM
+            ar           : ar_none;
+            res          : res_none;
+            dbg          : dbg_none;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 4;
+                loopalign       : 4;
+                jumpalign       : 0;
+                jumpalignskipmax    : 0;
+                coalescealign   : 0;
+                coalescealignskipmax: 0;
+                constalignmin   : 0;
+                constalignmax   : 4;
+                varalignmin     : 4;
+                varalignmax     : 4;
+                localalignmin   : 4;
+                localalignmax   : 4;
+                recordalignmin  : 0;
+                recordalignmax  : 2;
+                maxCrecordalign : 4
+              );
+            first_parm_offset : 0;
+            stacksize   : 262144;
+            stackalign   : 4;
+            abi          : abi_default;
+            llvmdatalayout : 'todo';
+          );
+
+
+  implementation
+
+end.
diff --git a/compiler/systems/t_wasi.pas b/compiler/systems/t_wasi.pas
new file mode 100644
index 0000000000..c61771fdbd
--- /dev/null
+++ b/compiler/systems/t_wasi.pas
@@ -0,0 +1,187 @@
+{
+    Copyright (c) 2019 by Dmitry Boyarintsev
+
+    This unit implements support import,export,link routines
+    for the WASI target
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit t_wasi;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  systems,
+
+  globtype, globals,
+  aasmbase,
+  cfileutl, cutils, cclasses,
+
+  import, export, aasmdata, aasmcpu,
+  fmodule, ogbase,
+
+  symsym, symdef,
+
+  link,
+
+  i_wasi, tgcpu;
+
+type
+
+  { texportlibwasi }
+
+  texportlibwasi=class(texportlib)
+      procedure preparelib(const s : string);override;
+      procedure exportprocedure(hp : texported_item);override;
+      procedure exportvar(hp : texported_item);override;
+      procedure generatelib;override;
+    end;
+
+  { timportlibwasi }
+  timportlibwasi = class(timportlib)
+      procedure generatelib;override;
+    end;
+
+  { tlinkerwasi }
+
+  tlinkerwasi=class(texternallinker)
+  public
+    constructor Create;override;
+    procedure SetDefaultInfo;override;
+
+    //function  MakeExecutable:boolean;override;
+    function  MakeSharedLibrary:boolean;override;
+  end;
+
+
+implementation
+
+{ timportlibwasi }
+
+  procedure timportlibwasi.generatelib;
+    begin
+    end;
+
+{ tlinkerwasi }
+
+constructor tlinkerwasi.Create;
+begin
+  inherited Create;
+end;
+
+procedure tlinkerwasi.SetDefaultInfo;
+begin
+  Info.DllCmd[1] := 'wasm-ld $SONAME $GCSECTIONS -o $EXE';
+  //Info.DllCmd[2] := 'wasmtool --exportrename $INPUT $EXE';
+end;
+
+function tlinkerwasi.MakeSharedLibrary: boolean;
+var
+  GCSectionsStr  : ansistring;
+  binstr, cmdstr : Tcmdstr;
+  InitStr,
+  FiniStr,
+  SoNameStr      : string[80];
+  mapstr,ltostr  : TCmdStr;
+  success        : Boolean;
+
+  tmp : TCmdStrListItem;
+  tempFileName : ansistring;
+begin
+  //Result := true;
+  //Result:=inherited MakeSharedLibrary;
+  if (cs_link_smart in current_settings.globalswitches) and
+     create_smartlink_sections then
+   GCSectionsStr:='--gc-sections'
+  else
+    GCSectionsStr:='';
+
+  SoNameStr:='';
+  SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+  Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
+
+  tmp := TCmdStrListItem(ObjectFiles.First);
+  while Assigned(tmp) do begin
+    cmdstr := tmp.Str+ ' ' + cmdstr;
+    tmp := TCmdStrListItem(tmp.Next);
+  end;
+
+  if HasExports then
+    cmdstr := cmdstr + ' --export-dynamic'; //' --export-dynamic';
+
+  cmdstr := cmdstr + ' --no-entry --allow-undefined';
+
+  if (cs_link_strip in current_settings.globalswitches) then
+   begin
+     { only remove non global symbols and debugging info for a library }
+     cmdstr := cmdstr + ' --strip-all';
+   end;
+
+  //Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  //Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+  //Replace(cmdstr,'$INIT',InitStr);
+  //Replace(cmdstr,'$FINI',FiniStr);
+  Replace(cmdstr,'$SONAME',SoNameStr);
+  //Replace(cmdstr,'$MAP',mapstr);
+  //Replace(cmdstr,'$LTO',ltostr);
+  Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+  writeln(utilsprefix+binstr,' ',cmdstr);
+  success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+
+  //SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+  //Replace(cmdstr,'$INPUT',current_module.objfilename );
+  //Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
+  //DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
+
+  MakeSharedLibrary:=success;
+end;
+
+{ texportlibwasi }
+
+procedure texportlibwasi.preparelib(const s: string);
+begin
+  //nothing to happen. wasm files are modules
+end;
+
+procedure texportlibwasi.exportprocedure(hp: texported_item);
+var
+  nm : TSymStr;
+begin
+  nm := tprocdef(tprocsym(hp.sym).ProcdefList[0]).mangledname;
+  current_asmdata.asmlists[al_exports].Concat(tai_impexp.create(hp.name^, nm, ie_Func));
+end;
+
+procedure texportlibwasi.exportvar(hp: texported_item);
+begin
+  //inherited exportvar(hp);
+end;
+
+procedure texportlibwasi.generatelib;
+begin
+  //inherited generatelib;
+end;
+
+initialization
+  RegisterTarget(system_wasi_info);
+  RegisterImport(system_wasm32_wasi, timportlibwasi);
+  RegisterExport(system_wasm32_wasi, texportlibwasi);
+  RegisterLinker(ld_wasi, tlinkerwasi);
+
+end.
diff --git a/compiler/wasm32/cputarg.pas b/compiler/wasm32/cputarg.pas
index 4f011cca0e..43b4ac35e8 100644
--- a/compiler/wasm32/cputarg.pas
+++ b/compiler/wasm32/cputarg.pas
@@ -39,6 +39,7 @@ implementation
              Targets
 **************************************}
       ,t_wasm
+      ,t_wasi
 
 {**************************************
              Assemblers