t_wasi.pas 7.9 KB

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