t_wasi.pas 8.9 KB

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