t_wasi.pas 9.8 KB

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