t_wasi.pas 8.7 KB

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