t_wasi.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. function GetDataSize(aExeOutput: TExeOutput): QWord;override;
  57. public
  58. constructor create;override;
  59. procedure InitSysInitUnitName;override;
  60. end;
  61. implementation
  62. uses
  63. SysUtils,
  64. verbose;
  65. { timportlibwasi }
  66. procedure timportlibwasi.generatelib;
  67. begin
  68. end;
  69. { tlinkerwasi }
  70. constructor tlinkerwasi.Create;
  71. begin
  72. inherited Create;
  73. end;
  74. procedure tlinkerwasi.SetDefaultInfo;
  75. begin
  76. with Info do
  77. begin
  78. ExeCmd[1] := 'wasm-ld -m wasm32 $SONAME $GCSECTIONS $MAP -z stack-size=$STACKSIZE $OPT -o $EXE';
  79. DllCmd[1] := 'wasm-ld -m wasm32 $SONAME $GCSECTIONS $MAP -z stack-size=$STACKSIZE $OPT -o $EXE';
  80. end;
  81. end;
  82. procedure tlinkerwasi.InitSysInitUnitName;
  83. begin
  84. if current_module.islibrary then
  85. sysinitunit:='si_dll'
  86. else
  87. sysinitunit:='si_prc';
  88. end;
  89. function tlinkerwasi.MakeExecutable:boolean;
  90. var
  91. GCSectionsStr : ansistring;
  92. binstr, cmdstr : Tcmdstr;
  93. InitStr,
  94. FiniStr,
  95. SoNameStr : string[80];
  96. mapstr,ltostr : TCmdStr;
  97. success : Boolean;
  98. tmp : TCmdStrListItem;
  99. tempFileName : ansistring;
  100. begin
  101. if not(cs_link_nolink in current_settings.globalswitches) then
  102. Message1(exec_i_linking,current_module.exefilename);
  103. { Create some replacements }
  104. mapstr:='';
  105. if (cs_link_map in current_settings.globalswitches) then
  106. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  107. if (cs_link_smart in current_settings.globalswitches) and
  108. create_smartlink_sections then
  109. GCSectionsStr:='--gc-sections'
  110. else
  111. GCSectionsStr:='';
  112. SoNameStr:='';
  113. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  114. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  115. tmp := TCmdStrListItem(ObjectFiles.First);
  116. while Assigned(tmp) do begin
  117. cmdstr := tmp.Str+ ' ' + cmdstr;
  118. tmp := TCmdStrListItem(tmp.Next);
  119. end;
  120. // if HasExports then
  121. // cmdstr := cmdstr + ' --export-dynamic'; //' --export-dynamic';
  122. cmdstr := cmdstr + ' --no-entry';
  123. if ts_wasm_threads in current_settings.targetswitches then
  124. begin
  125. cmdstr := cmdstr + ' --import-memory --shared-memory --initial-memory=16777216 --max-memory=16777216 --global-base=1024';
  126. end;
  127. if (cs_link_strip in current_settings.globalswitches) then
  128. begin
  129. { only remove non global symbols and debugging info for a library }
  130. cmdstr := cmdstr + ' --strip-all';
  131. end;
  132. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  133. //Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  134. //Replace(cmdstr,'$INIT',InitStr);
  135. //Replace(cmdstr,'$FINI',FiniStr);
  136. Replace(cmdstr,'$STACKSIZE',tostr(stacksize));
  137. Replace(cmdstr,'$SONAME',SoNameStr);
  138. Replace(cmdstr,'$MAP',mapstr);
  139. //Replace(cmdstr,'$LTO',ltostr);
  140. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  141. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
  142. MakeExecutable:=success;
  143. end;
  144. function tlinkerwasi.MakeSharedLibrary: boolean;
  145. var
  146. GCSectionsStr : ansistring;
  147. binstr, cmdstr : Tcmdstr;
  148. InitStr,
  149. FiniStr,
  150. SoNameStr : string[80];
  151. mapstr,ltostr : TCmdStr;
  152. success : Boolean;
  153. tmp : TCmdStrListItem;
  154. tempFileName : ansistring;
  155. begin
  156. Result:=false;
  157. if not(cs_link_nolink in current_settings.globalswitches) then
  158. Message1(exec_i_linking,current_module.sharedlibfilename);
  159. { Create some replacements }
  160. mapstr:='';
  161. if (cs_link_map in current_settings.globalswitches) then
  162. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  163. if (cs_link_smart in current_settings.globalswitches) and
  164. create_smartlink_sections then
  165. GCSectionsStr:='--gc-sections'
  166. else
  167. GCSectionsStr:='';
  168. SoNameStr:='';
  169. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  170. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  171. tmp := TCmdStrListItem(ObjectFiles.First);
  172. while Assigned(tmp) do begin
  173. cmdstr := tmp.Str+ ' ' + cmdstr;
  174. tmp := TCmdStrListItem(tmp.Next);
  175. end;
  176. // if HasExports then
  177. // cmdstr := cmdstr + ' --export-dynamic'; //' --export-dynamic';
  178. cmdstr := cmdstr + ' --no-entry';
  179. if (cs_link_strip in current_settings.globalswitches) then
  180. begin
  181. { only remove non global symbols and debugging info for a library }
  182. cmdstr := cmdstr + ' --strip-all';
  183. end;
  184. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  185. //Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  186. //Replace(cmdstr,'$INIT',InitStr);
  187. //Replace(cmdstr,'$FINI',FiniStr);
  188. Replace(cmdstr,'$STACKSIZE',tostr(stacksize));
  189. Replace(cmdstr,'$SONAME',SoNameStr);
  190. Replace(cmdstr,'$MAP',mapstr);
  191. //Replace(cmdstr,'$LTO',ltostr);
  192. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  193. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
  194. MakeSharedLibrary:=success;
  195. end;
  196. { texportlibwasi }
  197. procedure texportlibwasi.preparelib(const s: string);
  198. begin
  199. //nothing to happen. wasm files are modules
  200. end;
  201. procedure texportlibwasi.exportprocedure(hp: texported_item);
  202. var
  203. nm : TSymStr;
  204. pd: tcpuprocdef;
  205. begin
  206. pd:=tcpuprocdef(tprocsym(hp.sym).ProcdefList[0]);
  207. if eo_promising_first in hp.options then
  208. pd.add_promising_export(hp.name^,false)
  209. else if eo_promising_last in hp.options then
  210. pd.add_promising_export(hp.name^,true)
  211. else
  212. begin
  213. nm := pd.mangledname;
  214. current_asmdata.asmlists[al_exports].Concat(tai_export_name.create(hp.name^, nm, ie_Func));
  215. end;
  216. end;
  217. procedure texportlibwasi.exportvar(hp: texported_item);
  218. begin
  219. //inherited exportvar(hp);
  220. end;
  221. procedure texportlibwasi.generatelib;
  222. begin
  223. //inherited generatelib;
  224. end;
  225. { TInternalLinkerWasi }
  226. procedure TInternalLinkerWasi.DefaultLinkScript;
  227. var
  228. s: TCmdStr;
  229. begin
  230. while not ObjectFiles.Empty do
  231. begin
  232. s:=ObjectFiles.GetFirst;
  233. if s<>'' then
  234. LinkScript.Concat('READOBJECT ' + maybequoted(s));
  235. end;
  236. LinkScript.Concat('EXESECTION .wasm_globals');
  237. LinkScript.Concat(' SYMBOL __stack_pointer');
  238. LinkScript.Concat(' OBJSECTION .wasm_globals.*');
  239. LinkScript.Concat('ENDEXESECTION');
  240. ScriptAddGenericSections('.wasm_tags,.text,.rodata,.data,.bss,.debug_frame,.debug_info,.debug_line,.debug_abbrev,.debug_aranges,.debug_ranges,.debug_str');
  241. end;
  242. function TInternalLinkerWasi.GetDataSize(aExeOutput: TExeOutput): QWord;
  243. begin
  244. Result:=aExeOutput.findexesection('.rodata').size +
  245. aExeOutput.findexesection('.data').size;
  246. end;
  247. constructor TInternalLinkerWasi.create;
  248. begin
  249. inherited create;
  250. CExeOutput:=TWasmExeOutput;
  251. CObjInput:=TWasmObjInput;
  252. end;
  253. procedure TInternalLinkerWasi.InitSysInitUnitName;
  254. begin
  255. if current_module.islibrary then
  256. sysinitunit:='si_dll'
  257. else
  258. sysinitunit:='si_prc';
  259. end;
  260. initialization
  261. RegisterTarget(system_wasm32_wasi_info);
  262. RegisterImport(system_wasm32_wasi, timportlibwasi);
  263. RegisterExport(system_wasm32_wasi, texportlibwasi);
  264. RegisterLinker(ld_int_wasi,TInternalLinkerWasi);
  265. RegisterLinker(ld_wasi, tlinkerwasi);
  266. end.