t_wasi.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. {
  2. Copyright (c) 2019 by Dmitry Boyarintsev
  3. This unit implements support import,export,link routines
  4. for the WASI target
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit t_wasi;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. systems,
  23. globtype, globals,
  24. aasmbase,
  25. cfileutl, cutils, cclasses,
  26. import, export, aasmdata, aasmcpu,
  27. fmodule, ogbase, ogwasm,
  28. symconst, symsym, symdef, symcpu,
  29. link,
  30. i_wasi, tgcpu;
  31. type
  32. { texportlibwasi }
  33. texportlibwasi=class(texportlib)
  34. procedure preparelib(const s : string);override;
  35. procedure exportprocedure(hp : texported_item);override;
  36. procedure exportvar(hp : texported_item);override;
  37. procedure generatelib;override;
  38. end;
  39. { timportlibwasi }
  40. timportlibwasi = class(timportlib)
  41. procedure generatelib;override;
  42. end;
  43. { tlinkerwasi }
  44. tlinkerwasi=class(texternallinker)
  45. public
  46. constructor Create;override;
  47. procedure SetDefaultInfo;override;
  48. procedure InitSysInitUnitName;override;
  49. function MakeExecutable:boolean;override;
  50. function MakeSharedLibrary:boolean;override;
  51. end;
  52. { TInternalLinkerWasi }
  53. TInternalLinkerWasi=class(tinternallinker)
  54. protected
  55. procedure DefaultLinkScript;override;
  56. public
  57. constructor create;override;
  58. end;
  59. implementation
  60. uses
  61. SysUtils,
  62. verbose;
  63. { timportlibwasi }
  64. procedure timportlibwasi.generatelib;
  65. begin
  66. end;
  67. { tlinkerwasi }
  68. constructor tlinkerwasi.Create;
  69. begin
  70. inherited Create;
  71. end;
  72. procedure tlinkerwasi.SetDefaultInfo;
  73. begin
  74. with Info do
  75. begin
  76. ExeCmd[1] := 'wasm-ld -m wasm32 $SONAME $GCSECTIONS $MAP -z stack-size=$STACKSIZE $OPT -o $EXE';
  77. DllCmd[1] := 'wasm-ld -m wasm32 $SONAME $GCSECTIONS $MAP -z stack-size=$STACKSIZE $OPT -o $EXE';
  78. end;
  79. end;
  80. procedure tlinkerwasi.InitSysInitUnitName;
  81. begin
  82. if current_module.islibrary then
  83. sysinitunit:='si_dll'
  84. else
  85. sysinitunit:='si_prc';
  86. end;
  87. function tlinkerwasi.MakeExecutable:boolean;
  88. var
  89. GCSectionsStr : ansistring;
  90. binstr, cmdstr : Tcmdstr;
  91. InitStr,
  92. FiniStr,
  93. SoNameStr : string[80];
  94. mapstr,ltostr : TCmdStr;
  95. success : Boolean;
  96. tmp : TCmdStrListItem;
  97. tempFileName : ansistring;
  98. begin
  99. if not(cs_link_nolink in current_settings.globalswitches) then
  100. Message1(exec_i_linking,current_module.exefilename);
  101. { Create some replacements }
  102. mapstr:='';
  103. if (cs_link_map in current_settings.globalswitches) then
  104. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  105. if (cs_link_smart in current_settings.globalswitches) and
  106. create_smartlink_sections then
  107. GCSectionsStr:='--gc-sections'
  108. else
  109. GCSectionsStr:='';
  110. SoNameStr:='';
  111. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  112. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  113. tmp := TCmdStrListItem(ObjectFiles.First);
  114. while Assigned(tmp) do begin
  115. cmdstr := tmp.Str+ ' ' + cmdstr;
  116. tmp := TCmdStrListItem(tmp.Next);
  117. end;
  118. // if HasExports then
  119. // cmdstr := cmdstr + ' --export-dynamic'; //' --export-dynamic';
  120. cmdstr := cmdstr + ' --no-entry';
  121. if ts_wasm_threads in current_settings.targetswitches then
  122. begin
  123. cmdstr := cmdstr + ' --import-memory --shared-memory --initial-memory=16777216 --max-memory=16777216 --global-base=1024';
  124. end;
  125. if (cs_link_strip in current_settings.globalswitches) then
  126. begin
  127. { only remove non global symbols and debugging info for a library }
  128. cmdstr := cmdstr + ' --strip-all';
  129. end;
  130. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  131. //Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  132. //Replace(cmdstr,'$INIT',InitStr);
  133. //Replace(cmdstr,'$FINI',FiniStr);
  134. Replace(cmdstr,'$STACKSIZE',tostr(stacksize));
  135. Replace(cmdstr,'$SONAME',SoNameStr);
  136. Replace(cmdstr,'$MAP',mapstr);
  137. //Replace(cmdstr,'$LTO',ltostr);
  138. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  139. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
  140. MakeExecutable:=success;
  141. end;
  142. function tlinkerwasi.MakeSharedLibrary: boolean;
  143. var
  144. GCSectionsStr : ansistring;
  145. binstr, cmdstr : Tcmdstr;
  146. InitStr,
  147. FiniStr,
  148. SoNameStr : string[80];
  149. mapstr,ltostr : TCmdStr;
  150. success : Boolean;
  151. tmp : TCmdStrListItem;
  152. tempFileName : ansistring;
  153. begin
  154. Result:=false;
  155. if not(cs_link_nolink in current_settings.globalswitches) then
  156. Message1(exec_i_linking,current_module.sharedlibfilename);
  157. { Create some replacements }
  158. mapstr:='';
  159. if (cs_link_map in current_settings.globalswitches) then
  160. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  161. if (cs_link_smart in current_settings.globalswitches) and
  162. create_smartlink_sections then
  163. GCSectionsStr:='--gc-sections'
  164. else
  165. GCSectionsStr:='';
  166. SoNameStr:='';
  167. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  168. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  169. tmp := TCmdStrListItem(ObjectFiles.First);
  170. while Assigned(tmp) do begin
  171. cmdstr := tmp.Str+ ' ' + cmdstr;
  172. tmp := TCmdStrListItem(tmp.Next);
  173. end;
  174. // if HasExports then
  175. // cmdstr := cmdstr + ' --export-dynamic'; //' --export-dynamic';
  176. cmdstr := cmdstr + ' --no-entry';
  177. if (cs_link_strip in current_settings.globalswitches) then
  178. begin
  179. { only remove non global symbols and debugging info for a library }
  180. cmdstr := cmdstr + ' --strip-all';
  181. end;
  182. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  183. //Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  184. //Replace(cmdstr,'$INIT',InitStr);
  185. //Replace(cmdstr,'$FINI',FiniStr);
  186. Replace(cmdstr,'$STACKSIZE',tostr(stacksize));
  187. Replace(cmdstr,'$SONAME',SoNameStr);
  188. Replace(cmdstr,'$MAP',mapstr);
  189. //Replace(cmdstr,'$LTO',ltostr);
  190. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  191. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
  192. MakeSharedLibrary:=success;
  193. end;
  194. { texportlibwasi }
  195. procedure texportlibwasi.preparelib(const s: string);
  196. begin
  197. //nothing to happen. wasm files are modules
  198. end;
  199. procedure texportlibwasi.exportprocedure(hp: texported_item);
  200. var
  201. nm : TSymStr;
  202. pd: tcpuprocdef;
  203. begin
  204. pd:=tcpuprocdef(tprocsym(hp.sym).ProcdefList[0]);
  205. if eo_promising_first in hp.options then
  206. pd.add_promising_export(hp.name^,false)
  207. else if eo_promising_last in hp.options then
  208. pd.add_promising_export(hp.name^,true)
  209. else
  210. begin
  211. nm := pd.mangledname;
  212. current_asmdata.asmlists[al_exports].Concat(tai_export_name.create(hp.name^, nm, ie_Func));
  213. end;
  214. end;
  215. procedure texportlibwasi.exportvar(hp: texported_item);
  216. begin
  217. //inherited exportvar(hp);
  218. end;
  219. procedure texportlibwasi.generatelib;
  220. begin
  221. //inherited generatelib;
  222. end;
  223. { TInternalLinkerWasi }
  224. procedure TInternalLinkerWasi.DefaultLinkScript;
  225. begin
  226. {TODO}
  227. end;
  228. constructor TInternalLinkerWasi.create;
  229. begin
  230. inherited create;
  231. CExeOutput:=TWasmExeOutput;
  232. CObjInput:=TWasmObjInput;
  233. end;
  234. initialization
  235. RegisterTarget(system_wasm32_wasi_info);
  236. RegisterImport(system_wasm32_wasi, timportlibwasi);
  237. RegisterExport(system_wasm32_wasi, texportlibwasi);
  238. RegisterLinker(ld_wasi, tlinkerwasi);
  239. end.