ogwasm.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. {
  2. Copyright (c) 2021 by Nikolay Nikolov
  3. Contains the WebAssembly binary module format reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogwasm;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,cpubase,
  25. { assembler }
  26. aasmbase,assemble,aasmcpu,
  27. { WebAssembly module format definitions }
  28. wasmbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. { TWasmObjSymbol }
  34. TWasmObjSymbol = class(TObjSymbol)
  35. ImportIndex: Integer;
  36. FuncIndex: Integer;
  37. SymbolIndex: Integer;
  38. constructor create(AList:TFPHashObjectList;const AName:string);
  39. function ImportOrFuncIndex: Integer;
  40. end;
  41. { TWasmObjRelocation }
  42. TWasmObjRelocation = class(TObjRelocation)
  43. end;
  44. { TWasmObjSymbolExtraData }
  45. TWasmObjSymbolExtraData = class(TFPHashObject)
  46. TypeIdx: Integer;
  47. ImportModule: string;
  48. ImportName: string;
  49. Locals: array of TWasmBasicType;
  50. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  51. procedure AddLocal(bastyp: TWasmBasicType);
  52. end;
  53. { TWasmObjSection }
  54. TWasmObjSection = class(TObjSection)
  55. public
  56. SegIdx: Integer;
  57. SegOfs: qword;
  58. FileSectionOfs: qword;
  59. function IsCode: Boolean;
  60. function IsData: Boolean;
  61. end;
  62. { TWasmObjData }
  63. TWasmObjData = class(TObjData)
  64. private
  65. FFuncTypes: array of TWasmFuncType;
  66. FObjSymbolsExtraDataList: TFPHashObjectList;
  67. FLastFuncName: string;
  68. function is_smart_section(atype:TAsmSectiontype):boolean;
  69. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  70. public
  71. constructor create(const n:string);override;
  72. destructor destroy; override;
  73. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  74. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  75. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  76. function AddFuncType(wft: TWasmFuncType): integer;
  77. procedure DeclareFuncType(ft: tai_functype);
  78. procedure DeclareImportModule(aim: tai_import_module);
  79. procedure DeclareImportName(ain: tai_import_name);
  80. procedure DeclareLocal(al: tai_local);
  81. end;
  82. { TWasmObjOutput }
  83. TWasmObjOutput = class(tObjOutput)
  84. private
  85. FData: TWasmObjData;
  86. FWasmRelocationCodeTable: tdynamicarray;
  87. FWasmRelocationCodeTableEntriesCount: Integer;
  88. FWasmRelocationDataTable: tdynamicarray;
  89. FWasmRelocationDataTableEntriesCount: Integer;
  90. FWasmSymbolTable: tdynamicarray;
  91. FWasmSymbolTableEntriesCount: Integer;
  92. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  93. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  94. FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of tdynamicarray;
  95. procedure WriteUleb(d: tdynamicarray; v: uint64);
  96. procedure WriteUleb(w: TObjectWriter; v: uint64);
  97. procedure WriteSleb(d: tdynamicarray; v: int64);
  98. procedure WriteByte(d: tdynamicarray; b: byte);
  99. procedure WriteName(d: tdynamicarray; const s: string);
  100. procedure WriteWasmSection(wsid: TWasmSectionID);
  101. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  102. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  103. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  104. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  105. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  106. function IsExternalFunction(sym: TObjSymbol): Boolean;
  107. procedure WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
  108. procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  109. procedure WriteSymbolTable;
  110. procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
  111. procedure WriteRelocationDataTable(DataSectionIndex: Integer);
  112. procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  113. procedure DoRelocations;
  114. procedure WriteRelocations;
  115. protected
  116. function writeData(Data:TObjData):boolean;override;
  117. public
  118. constructor create(AWriter:TObjectWriter);override;
  119. destructor destroy;override;
  120. end;
  121. { TWasmAssembler }
  122. TWasmAssembler = class(tinternalassembler)
  123. constructor create(info: pasminfo; smart:boolean);override;
  124. end;
  125. implementation
  126. uses
  127. verbose;
  128. procedure WriteUleb5(d: tdynamicarray; v: uint64);
  129. var
  130. b: byte;
  131. i: Integer;
  132. begin
  133. for i:=1 to 5 do
  134. begin
  135. b:=byte(v) and 127;
  136. v:=v shr 7;
  137. if i<>5 then
  138. b:=b or 128;
  139. d.write(b,1);
  140. end;
  141. end;
  142. procedure WriteUleb5(d: tobjsection; v: uint64);
  143. var
  144. b: byte;
  145. i: Integer;
  146. begin
  147. for i:=1 to 5 do
  148. begin
  149. b:=byte(v) and 127;
  150. v:=v shr 7;
  151. if i<>5 then
  152. b:=b or 128;
  153. d.write(b,1);
  154. end;
  155. end;
  156. procedure WriteSleb5(d: tdynamicarray; v: int64);
  157. var
  158. b: byte;
  159. i: Integer;
  160. begin
  161. for i:=1 to 5 do
  162. begin
  163. b:=byte(v) and 127;
  164. v:=SarInt64(v,7);
  165. if i<>5 then
  166. b:=b or 128;
  167. d.write(b,1);
  168. end;
  169. end;
  170. procedure WriteSleb5(d: tobjsection; v: int64);
  171. var
  172. b: byte;
  173. i: Integer;
  174. begin
  175. for i:=1 to 5 do
  176. begin
  177. b:=byte(v) and 127;
  178. v:=SarInt64(v,7);
  179. if i<>5 then
  180. b:=b or 128;
  181. d.write(b,1);
  182. end;
  183. end;
  184. function ReadUleb(d: tdynamicarray): uint64;
  185. var
  186. b: byte;
  187. shift:integer;
  188. begin
  189. b:=0;
  190. result:=0;
  191. shift:=0;
  192. repeat
  193. d.read(b,1);
  194. result:=result or (uint64(b and 127) shl shift);
  195. inc(shift,7);
  196. until (b and 128)=0;
  197. end;
  198. function ReadSleb(d: tdynamicarray): int64;
  199. var
  200. b: byte;
  201. shift:integer;
  202. begin
  203. result:=0;
  204. shift:=0;
  205. repeat
  206. d.read(b,1);
  207. result:=result or (uint64(b and 127) shl shift);
  208. inc(shift,7);
  209. until (b and 128)=0;
  210. if (b and 64)<>0 then
  211. result:=result or (high(uint64) shl shift);
  212. end;
  213. procedure AddSleb5(d: tdynamicarray; v: int64);
  214. var
  215. q: Int64;
  216. p: LongWord;
  217. begin
  218. p:=d.Pos;
  219. q:=ReadSleb(d);
  220. q:=q+v;
  221. d.seek(p);
  222. WriteSleb5(d,q);
  223. end;
  224. procedure AddUleb5(d: tdynamicarray; v: int64);
  225. var
  226. q: UInt64;
  227. p: LongWord;
  228. begin
  229. p:=d.Pos;
  230. q:=ReadUleb(d);
  231. q:=q+v;
  232. d.seek(p);
  233. WriteUleb5(d,q);
  234. end;
  235. {****************************************************************************
  236. TWasmObjSymbol
  237. ****************************************************************************}
  238. constructor TWasmObjSymbol.create(AList: TFPHashObjectList; const AName: string);
  239. begin
  240. inherited create(AList,AName);
  241. ImportIndex:=-1;
  242. FuncIndex:=-1;
  243. SymbolIndex:=-1;
  244. end;
  245. function TWasmObjSymbol.ImportOrFuncIndex: Integer;
  246. begin
  247. if ImportIndex<>-1 then
  248. result:=ImportIndex
  249. else if FuncIndex<>-1 then
  250. result:=FuncIndex
  251. else
  252. internalerror(2021092601);
  253. end;
  254. {****************************************************************************
  255. TWasmObjSymbolExtraData
  256. ****************************************************************************}
  257. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  258. begin
  259. inherited Create(HashObjectList,s);
  260. TypeIdx:=-1;
  261. end;
  262. procedure TWasmObjSymbolExtraData.AddLocal(bastyp: TWasmBasicType);
  263. begin
  264. SetLength(Locals,Length(Locals)+1);
  265. Locals[High(Locals)]:=bastyp;
  266. end;
  267. {****************************************************************************
  268. TWasmObjSection
  269. ****************************************************************************}
  270. function TWasmObjSection.IsCode: Boolean;
  271. const
  272. CodePrefix = '.text';
  273. begin
  274. result:=(Length(Name)>=Length(CodePrefix)) and
  275. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  276. end;
  277. function TWasmObjSection.IsData: Boolean;
  278. begin
  279. result:=not IsCode;
  280. end;
  281. {****************************************************************************
  282. TWasmObjData
  283. ****************************************************************************}
  284. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  285. begin
  286. { For bss we need to set some flags that are target dependent,
  287. it is easier to disable it for smartlinking. It doesn't take up
  288. filespace }
  289. result:=not(target_info.system in systems_darwin) and
  290. create_smartlink_sections and
  291. (atype<>sec_toc) and
  292. (atype<>sec_user) and
  293. { on embedded systems every byte counts, so smartlink bss too }
  294. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  295. end;
  296. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  297. const aname: string; aorder: TAsmSectionOrder): string;
  298. const
  299. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  300. '.text',
  301. '.data',
  302. { why doesn't .rodata work? (FK) }
  303. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  304. { vtables (and anything else containing relocations), otherwise those are }
  305. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  306. { vtable for a class called Window: }
  307. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  308. { TODO: .data.ro not yet working}
  309. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  310. '.rodata',
  311. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  312. '.data',
  313. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  314. '.rodata',
  315. '.bss',
  316. '.threadvar',
  317. '.pdata',
  318. '', { stubs }
  319. '__DATA,__nl_symbol_ptr',
  320. '__DATA,__la_symbol_ptr',
  321. '__DATA,__mod_init_func',
  322. '__DATA,__mod_term_func',
  323. '.stab',
  324. '.stabstr',
  325. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  326. '.eh_frame',
  327. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  328. '.fpc',
  329. '.toc',
  330. '.init',
  331. '.fini',
  332. '.objc_class',
  333. '.objc_meta_class',
  334. '.objc_cat_cls_meth',
  335. '.objc_cat_inst_meth',
  336. '.objc_protocol',
  337. '.objc_string_object',
  338. '.objc_cls_meth',
  339. '.objc_inst_meth',
  340. '.objc_cls_refs',
  341. '.objc_message_refs',
  342. '.objc_symbols',
  343. '.objc_category',
  344. '.objc_class_vars',
  345. '.objc_instance_vars',
  346. '.objc_module_info',
  347. '.objc_class_names',
  348. '.objc_meth_var_types',
  349. '.objc_meth_var_names',
  350. '.objc_selector_strs',
  351. '.objc_protocol_ext',
  352. '.objc_class_ext',
  353. '.objc_property',
  354. '.objc_image_info',
  355. '.objc_cstring_object',
  356. '.objc_sel_fixup',
  357. '__DATA,__objc_data',
  358. '__DATA,__objc_const',
  359. '.objc_superrefs',
  360. '__DATA, __datacoal_nt,coalesced',
  361. '.objc_classlist',
  362. '.objc_nlclasslist',
  363. '.objc_catlist',
  364. '.obcj_nlcatlist',
  365. '.objc_protolist',
  366. '.stack',
  367. '.heap',
  368. '.gcc_except_table',
  369. '.ARM.attributes'
  370. );
  371. var
  372. sep : string[3];
  373. secname : string;
  374. begin
  375. secname:=secnames[atype];
  376. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  377. begin
  378. result:=secname+'.'+aname;
  379. exit;
  380. end;
  381. if atype=sec_threadvar then
  382. begin
  383. if (target_info.system in (systems_windows+systems_wince)) then
  384. secname:='.tls'
  385. else if (target_info.system in systems_linux) then
  386. secname:='.tbss';
  387. end;
  388. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  389. Thus, data which normally goes into .rodata and .rodata_norel sections must
  390. end up in .data section }
  391. if (atype in [sec_rodata,sec_rodata_norel]) and
  392. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  393. secname:='.data';
  394. { Windows correctly handles reallocations in readonly sections }
  395. if (atype=sec_rodata) and
  396. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  397. secname:='.rodata';
  398. { section type user gives the user full controll on the section name }
  399. if atype=sec_user then
  400. secname:=aname;
  401. if is_smart_section(atype) and (aname<>'') then
  402. begin
  403. case aorder of
  404. secorder_begin :
  405. sep:='.b_';
  406. secorder_end :
  407. sep:='.z_';
  408. else
  409. sep:='.n_';
  410. end;
  411. result:=secname+sep+aname
  412. end
  413. else
  414. result:=secname;
  415. end;
  416. constructor TWasmObjData.create(const n: string);
  417. begin
  418. inherited;
  419. CObjSection:=TWasmObjSection;
  420. CObjSymbol:=TWasmObjSymbol;
  421. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  422. end;
  423. destructor TWasmObjData.destroy;
  424. var
  425. i: Integer;
  426. begin
  427. FObjSymbolsExtraDataList.Free;
  428. for i:=low(FFuncTypes) to high(FFuncTypes) do
  429. begin
  430. FFuncTypes[i].free;
  431. FFuncTypes[i]:=nil;
  432. end;
  433. inherited destroy;
  434. end;
  435. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  436. const aname: string; aorder: TAsmSectionOrder): string;
  437. begin
  438. if (atype=sec_fpc) or (atype=sec_threadvar) then
  439. atype:=sec_data;
  440. Result:=sectionname_gas(atype, aname, aorder);
  441. end;
  442. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  443. p: TObjSymbol; Reloctype: TObjRelocationType);
  444. const
  445. leb_zero: array[0..4] of byte=($80,$80,$80,$80,$00);
  446. var
  447. objreloc: TWasmObjRelocation;
  448. begin
  449. if CurrObjSec=nil then
  450. internalerror(200403072);
  451. objreloc:=nil;
  452. case Reloctype of
  453. RELOC_FUNCTION_INDEX_LEB:
  454. begin
  455. if Data<>0 then
  456. internalerror(2021092502);
  457. if len<>5 then
  458. internalerror(2021092503);
  459. if not assigned(p) then
  460. internalerror(2021092504);
  461. if p.bind<>AB_EXTERNAL then
  462. internalerror(2021092505);
  463. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  464. CurrObjSec.ObjRelocations.Add(objreloc);
  465. writebytes(leb_zero,5);
  466. end;
  467. RELOC_MEMORY_ADDR_LEB,
  468. RELOC_MEMORY_ADDR_SLEB:
  469. begin
  470. if (Reloctype=RELOC_MEMORY_ADDR_LEB) and (Data<0) then
  471. internalerror(2021092602);
  472. if len<>5 then
  473. internalerror(2021092503);
  474. if not assigned(p) then
  475. internalerror(2021092504);
  476. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  477. CurrObjSec.ObjRelocations.Add(objreloc);
  478. if RelocType=RELOC_MEMORY_ADDR_LEB then
  479. WriteUleb5(CurrObjSec,Data)
  480. else
  481. WriteSleb5(CurrObjSec,Data);
  482. end;
  483. RELOC_ABSOLUTE:
  484. begin
  485. { todo... }
  486. end;
  487. else
  488. internalerror(2021092501);
  489. end;
  490. end;
  491. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  492. begin
  493. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  494. if not assigned(result) then
  495. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  496. end;
  497. function TWasmObjData.AddFuncType(wft: TWasmFuncType): integer;
  498. var
  499. i: Integer;
  500. begin
  501. for i:=low(FFuncTypes) to high(FFuncTypes) do
  502. if wft.Equals(FFuncTypes[i]) then
  503. exit(i);
  504. result:=Length(FFuncTypes);
  505. SetLength(FFuncTypes,result+1);
  506. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  507. end;
  508. procedure TWasmObjData.DeclareFuncType(ft: tai_functype);
  509. var
  510. i: Integer;
  511. ObjSymExtraData: TWasmObjSymbolExtraData;
  512. begin
  513. FLastFuncName:=ft.funcname;
  514. i:=AddFuncType(ft.functype);
  515. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  516. ObjSymExtraData.TypeIdx:=i;
  517. end;
  518. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  519. var
  520. ObjSymExtraData: TWasmObjSymbolExtraData;
  521. begin
  522. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  523. ObjSymExtraData.ImportModule:=aim.importmodule;
  524. end;
  525. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  526. var
  527. ObjSymExtraData: TWasmObjSymbolExtraData;
  528. begin
  529. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  530. ObjSymExtraData.ImportName:=ain.importname;
  531. end;
  532. procedure TWasmObjData.DeclareLocal(al: tai_local);
  533. var
  534. ObjSymExtraData: TWasmObjSymbolExtraData;
  535. begin
  536. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  537. ObjSymExtraData.AddLocal(al.bastyp);
  538. end;
  539. {****************************************************************************
  540. TWasmObjOutput
  541. ****************************************************************************}
  542. procedure TWasmObjOutput.WriteUleb(d: tdynamicarray; v: uint64);
  543. var
  544. b: byte;
  545. begin
  546. repeat
  547. b:=byte(v) and 127;
  548. v:=v shr 7;
  549. if v<>0 then
  550. b:=b or 128;
  551. d.write(b,1);
  552. until v=0;
  553. end;
  554. procedure TWasmObjOutput.WriteUleb(w: TObjectWriter; v: uint64);
  555. var
  556. b: byte;
  557. begin
  558. repeat
  559. b:=byte(v) and 127;
  560. v:=v shr 7;
  561. if v<>0 then
  562. b:=b or 128;
  563. w.write(b,1);
  564. until v=0;
  565. end;
  566. procedure TWasmObjOutput.WriteSleb(d: tdynamicarray; v: int64);
  567. var
  568. b: byte;
  569. Done: Boolean=false;
  570. begin
  571. repeat
  572. b:=byte(v) and 127;
  573. v:=SarInt64(v,7);
  574. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  575. Done:=true
  576. else
  577. b:=b or 128;
  578. d.write(b,1);
  579. until Done;
  580. end;
  581. procedure TWasmObjOutput.WriteByte(d: tdynamicarray; b: byte);
  582. begin
  583. d.write(b,1);
  584. end;
  585. procedure TWasmObjOutput.WriteName(d: tdynamicarray; const s: string);
  586. begin
  587. WriteUleb(d,Length(s));
  588. d.writestr(s);
  589. end;
  590. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  591. var
  592. b: byte;
  593. begin
  594. b:=ord(wsid);
  595. Writer.write(b,1);
  596. WriteUleb(Writer,FWasmSections[wsid].size);
  597. Writer.writearray(FWasmSections[wsid]);
  598. end;
  599. procedure TWasmObjOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  600. var
  601. b: byte;
  602. begin
  603. b:=0;
  604. Writer.write(b,1);
  605. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  606. Writer.writearray(FWasmCustomSections[wcst]);
  607. end;
  608. procedure TWasmObjOutput.CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  609. var
  610. buf: array [0..4095] of byte;
  611. bs: Integer;
  612. begin
  613. while size>0 do
  614. begin
  615. if size<SizeOf(buf) then
  616. bs:=Integer(size)
  617. else
  618. bs:=SizeOf(buf);
  619. src.read(buf,bs);
  620. dest.write(buf,bs);
  621. dec(size,bs);
  622. end;
  623. end;
  624. procedure TWasmObjOutput.WriteZeros(dest: tdynamicarray; size: QWord);
  625. var
  626. buf : array[0..1023] of byte;
  627. bs: Integer;
  628. begin
  629. fillchar(buf,sizeof(buf),0);
  630. while size>0 do
  631. begin
  632. if size<SizeOf(buf) then
  633. bs:=Integer(size)
  634. else
  635. bs:=SizeOf(buf);
  636. dest.write(buf,bs);
  637. dec(size,bs);
  638. end;
  639. end;
  640. procedure TWasmObjOutput.WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  641. var
  642. i: Integer;
  643. begin
  644. WriteUleb(dest,Length(wrt));
  645. for i:=low(wrt) to high(wrt) do
  646. WriteWasmBasicType(dest,wrt[i]);
  647. end;
  648. procedure TWasmObjOutput.WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  649. begin
  650. case wbt of
  651. wbt_i32:
  652. WriteByte(dest,$7F);
  653. wbt_i64:
  654. WriteByte(dest,$7E);
  655. wbt_f32:
  656. WriteByte(dest,$7D);
  657. wbt_f64:
  658. WriteByte(dest,$7C);
  659. end;
  660. end;
  661. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  662. begin
  663. result:=(sym.bind=AB_EXTERNAL) and (TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name)<>nil);
  664. end;
  665. procedure TWasmObjOutput.WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
  666. var
  667. i,
  668. rle_entries,
  669. cnt: Integer;
  670. lasttype: TWasmBasicType;
  671. begin
  672. if Length(ed.Locals)=0 then
  673. begin
  674. WriteUleb(dest,0);
  675. exit;
  676. end;
  677. rle_entries:=1;
  678. for i:=low(ed.Locals)+1 to high(ed.Locals) do
  679. if ed.Locals[i]<>ed.Locals[i-1] then
  680. inc(rle_entries);
  681. WriteUleb(dest,rle_entries);
  682. lasttype:=ed.Locals[Low(ed.Locals)];
  683. cnt:=1;
  684. for i:=low(ed.Locals)+1 to high(ed.Locals) do
  685. if ed.Locals[i]=ed.Locals[i-1] then
  686. inc(cnt)
  687. else
  688. begin
  689. WriteUleb(dest,cnt);
  690. WriteWasmBasicType(dest,lasttype);
  691. lasttype:=ed.Locals[i];
  692. cnt:=1;
  693. end;
  694. WriteUleb(dest,cnt);
  695. WriteWasmBasicType(dest,lasttype);
  696. end;
  697. procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  698. var
  699. encoded_locals: tdynamicarray;
  700. ObjSymExtraData: TWasmObjSymbolExtraData;
  701. codelen: LongWord;
  702. ObjSection: TWasmObjSection;
  703. codeexprlen: QWord;
  704. begin
  705. ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  706. ObjSection:=TWasmObjSection(objsym.objsection);
  707. ObjSection.Data.seek(objsym.address);
  708. codeexprlen:=ObjSection.Size-objsym.address;
  709. encoded_locals:=tdynamicarray.Create(64);
  710. WriteFunctionLocals(encoded_locals,ObjSymExtraData);
  711. codelen:=encoded_locals.size+codeexprlen+1;
  712. WriteUleb(dest,codelen);
  713. encoded_locals.seek(0);
  714. CopyDynamicArray(encoded_locals,dest,encoded_locals.size);
  715. ObjSection.FileSectionOfs:=dest.size-objsym.offset;
  716. CopyDynamicArray(ObjSection.Data,dest,codeexprlen);
  717. WriteByte(dest,$0B);
  718. encoded_locals.Free;
  719. end;
  720. procedure TWasmObjOutput.WriteSymbolTable;
  721. begin
  722. WriteUleb(FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTableEntriesCount);
  723. FWasmSymbolTable.seek(0);
  724. CopyDynamicArray(FWasmSymbolTable,FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTable.size);
  725. end;
  726. procedure TWasmObjOutput.WriteRelocationCodeTable(CodeSectionIndex: Integer);
  727. begin
  728. WriteUleb(FWasmCustomSections[wcstRelocCode],CodeSectionIndex);
  729. WriteUleb(FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTableEntriesCount);
  730. FWasmRelocationCodeTable.seek(0);
  731. CopyDynamicArray(FWasmRelocationCodeTable,FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTable.size);
  732. end;
  733. procedure TWasmObjOutput.WriteRelocationDataTable(DataSectionIndex: Integer);
  734. begin
  735. WriteUleb(FWasmCustomSections[wcstRelocData],DataSectionIndex);
  736. WriteUleb(FWasmCustomSections[wcstRelocData],FWasmRelocationDataTableEntriesCount);
  737. FWasmRelocationDataTable.seek(0);
  738. CopyDynamicArray(FWasmRelocationDataTable,FWasmCustomSections[wcstRelocData],FWasmRelocationDataTable.size);
  739. end;
  740. procedure TWasmObjOutput.WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  741. begin
  742. if FWasmLinkingSubsections[wlst].size>0 then
  743. begin
  744. WriteByte(FWasmCustomSections[wcstLinking],Ord(wlst));
  745. WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  746. FWasmLinkingSubsections[wlst].seek(0);
  747. CopyDynamicArray(FWasmLinkingSubsections[wlst],FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  748. end;
  749. end;
  750. procedure TWasmObjOutput.DoRelocations;
  751. var
  752. si, ri: Integer;
  753. objsec: TWasmObjSection;
  754. objrel: TWasmObjRelocation;
  755. begin
  756. for si:=0 to FData.ObjSectionList.Count-1 do
  757. begin
  758. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  759. for ri:=0 to objsec.ObjRelocations.Count-1 do
  760. begin
  761. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  762. case objrel.typ of
  763. RELOC_FUNCTION_INDEX_LEB:
  764. begin
  765. if not assigned(objrel.symbol) then
  766. internalerror(2021092509);
  767. objsec.Data.seek(objrel.DataOffset);
  768. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).ImportOrFuncIndex);
  769. end;
  770. RELOC_MEMORY_ADDR_SLEB:
  771. begin
  772. if not assigned(objrel.symbol) then
  773. internalerror(2021092605);
  774. if objrel.symbol.bind<>AB_EXTERNAL then
  775. begin
  776. objsec.Data.seek(objrel.DataOffset);
  777. AddSleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  778. end;
  779. end;
  780. RELOC_MEMORY_ADDR_LEB:
  781. begin
  782. if not assigned(objrel.symbol) then
  783. internalerror(2021092606);
  784. if objrel.symbol.bind<>AB_EXTERNAL then
  785. begin
  786. objsec.Data.seek(objrel.DataOffset);
  787. AddUleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  788. end;
  789. end;
  790. else
  791. internalerror(2021092510);
  792. end;
  793. end;
  794. end;
  795. end;
  796. procedure TWasmObjOutput.WriteRelocations;
  797. var
  798. si, ri: Integer;
  799. objsec: TWasmObjSection;
  800. objrel: TWasmObjRelocation;
  801. relout: tdynamicarray;
  802. relcount: PInteger;
  803. begin
  804. for si:=0 to FData.ObjSectionList.Count-1 do
  805. begin
  806. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  807. if objsec.IsCode then
  808. begin
  809. relout:=FWasmRelocationCodeTable;
  810. relcount:=@FWasmRelocationCodeTableEntriesCount;
  811. end
  812. else
  813. begin
  814. relout:=FWasmRelocationDataTable;
  815. relcount:=@FWasmRelocationDataTableEntriesCount;
  816. end;
  817. for ri:=0 to objsec.ObjRelocations.Count-1 do
  818. begin
  819. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  820. case objrel.typ of
  821. RELOC_FUNCTION_INDEX_LEB:
  822. begin
  823. if not assigned(objrel.symbol) then
  824. internalerror(2021092508);
  825. Inc(relcount^);
  826. WriteByte(relout,Ord(R_WASM_FUNCTION_INDEX_LEB));
  827. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  828. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  829. end;
  830. RELOC_MEMORY_ADDR_LEB:
  831. begin
  832. if not assigned(objrel.symbol) then
  833. internalerror(2021092603);
  834. Inc(relcount^);
  835. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_LEB));
  836. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  837. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  838. WriteUleb(relout,0); { addend to add to the address }
  839. end;
  840. RELOC_MEMORY_ADDR_SLEB:
  841. begin
  842. if not assigned(objrel.symbol) then
  843. internalerror(2021092604);
  844. Inc(relcount^);
  845. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_SLEB));
  846. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  847. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  848. WriteUleb(relout,0); { addend to add to the address }
  849. end;
  850. else
  851. internalerror(2021092507);
  852. end;
  853. end;
  854. end;
  855. end;
  856. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  857. var
  858. i: Integer;
  859. objsec: TWasmObjSection;
  860. segment_count: Integer = 0;
  861. cur_seg_ofs: qword = 0;
  862. types_count,
  863. imports_count, NextImportFunctionIndex, NextFunctionIndex: Integer;
  864. import_functions_count: Integer = 0;
  865. functions_count: Integer = 0;
  866. objsym: TWasmObjSymbol;
  867. cust_sec: TWasmCustomSectionType;
  868. begin
  869. FData:=TWasmObjData(Data);
  870. { each custom sections starts with its name }
  871. for cust_sec in TWasmCustomSectionType do
  872. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  873. WriteUleb(FWasmCustomSections[wcstLinking],2); { linking metadata version }
  874. for i:=0 to Data.ObjSymbolList.Count-1 do
  875. begin
  876. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  877. if IsExternalFunction(objsym) then
  878. Inc(import_functions_count);
  879. if objsym.typ=AT_FUNCTION then
  880. Inc(functions_count);
  881. end;
  882. types_count:=Length(FData.FFuncTypes);
  883. WriteUleb(FWasmSections[wsiType],types_count);
  884. for i:=0 to types_count-1 do
  885. with FData.FFuncTypes[i] do
  886. begin
  887. WriteByte(FWasmSections[wsiType],$60);
  888. WriteWasmResultType(FWasmSections[wsiType],params);
  889. WriteWasmResultType(FWasmSections[wsiType],results);
  890. end;
  891. for i:=0 to Data.ObjSectionList.Count-1 do
  892. begin
  893. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  894. if objsec.IsCode then
  895. objsec.SegIdx:=-1
  896. else
  897. begin
  898. objsec.SegIdx:=segment_count;
  899. objsec.SegOfs:=cur_seg_ofs;
  900. Inc(segment_count);
  901. Inc(cur_seg_ofs,objsec.Size);
  902. end;
  903. end;
  904. WriteUleb(FWasmSections[wsiData],segment_count);
  905. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  906. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],segment_count);
  907. for i:=0 to Data.ObjSectionList.Count-1 do
  908. begin
  909. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  910. if objsec.IsData then
  911. begin
  912. WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],objsec.Name);
  913. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(objsec.SecAlign));
  914. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],0); { flags }
  915. WriteByte(FWasmSections[wsiData],0);
  916. WriteByte(FWasmSections[wsiData],$41);
  917. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  918. WriteByte(FWasmSections[wsiData],$0b);
  919. WriteUleb(FWasmSections[wsiData],objsec.Size);
  920. objsec.FileSectionOfs:=FWasmSections[wsiData].size;
  921. if oso_Data in objsec.SecOptions then
  922. begin
  923. objsec.Data.seek(0);
  924. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  925. end
  926. else
  927. begin
  928. WriteZeros(FWasmSections[wsiData],objsec.Size);
  929. end;
  930. end;
  931. end;
  932. imports_count:=3+import_functions_count;
  933. WriteUleb(FWasmSections[wsiImport],imports_count);
  934. { import[0] }
  935. WriteName(FWasmSections[wsiImport],'env');
  936. WriteName(FWasmSections[wsiImport],'__linear_memory');
  937. WriteByte(FWasmSections[wsiImport],$02); { mem }
  938. WriteByte(FWasmSections[wsiImport],$00); { min }
  939. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  940. { import[1] }
  941. WriteName(FWasmSections[wsiImport],'env');
  942. WriteName(FWasmSections[wsiImport],'__stack_pointer');
  943. WriteByte(FWasmSections[wsiImport],$03); { global }
  944. WriteByte(FWasmSections[wsiImport],$7F); { i32 }
  945. WriteByte(FWasmSections[wsiImport],$01); { var }
  946. { import[2]..import[imports_count-2] }
  947. NextImportFunctionIndex:=0;
  948. for i:=0 to Data.ObjSymbolList.Count-1 do
  949. begin
  950. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  951. if IsExternalFunction(objsym) then
  952. begin
  953. objsym.ImportIndex:=NextImportFunctionIndex;
  954. Inc(NextImportFunctionIndex);
  955. WriteName(FWasmSections[wsiImport],'env');
  956. WriteName(FWasmSections[wsiImport],objsym.Name);
  957. WriteByte(FWasmSections[wsiImport],$00); { func }
  958. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  959. end;
  960. end;
  961. { import[imports_count-1] }
  962. WriteName(FWasmSections[wsiImport],'env');
  963. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  964. WriteByte(FWasmSections[wsiImport],$01); { table }
  965. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  966. WriteByte(FWasmSections[wsiImport],$00); { min }
  967. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  968. WriteUleb(FWasmSections[wsiFunction],functions_count);
  969. NextFunctionIndex:=NextImportFunctionIndex;
  970. for i:=0 to Data.ObjSymbolList.Count-1 do
  971. begin
  972. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  973. if objsym.typ=AT_FUNCTION then
  974. begin
  975. objsym.FuncIndex:=NextFunctionIndex;
  976. Inc(NextFunctionIndex);
  977. WriteUleb(FWasmSections[wsiFunction],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  978. end;
  979. end;
  980. for i:=0 to Data.ObjSymbolList.Count-1 do
  981. begin
  982. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  983. if IsExternalFunction(objsym) then
  984. begin
  985. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  986. Inc(FWasmSymbolTableEntriesCount);
  987. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  988. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  989. WriteUleb(FWasmSymbolTable,objsym.ImportIndex);
  990. end
  991. else if objsym.typ=AT_FUNCTION then
  992. begin
  993. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  994. Inc(FWasmSymbolTableEntriesCount);
  995. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  996. WriteUleb(FWasmSymbolTable,0);
  997. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  998. WriteName(FWasmSymbolTable,objsym.Name);
  999. end
  1000. else if (objsym.typ=AT_DATA) or ((objsym.typ=AT_NONE) and (objsym.bind=AB_EXTERNAL)) then
  1001. begin
  1002. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1003. Inc(FWasmSymbolTableEntriesCount);
  1004. WriteByte(FWasmSymbolTable,Ord(SYMTAB_DATA));
  1005. if objsym.bind=AB_GLOBAL then
  1006. WriteUleb(FWasmSymbolTable,0)
  1007. else if objsym.bind=AB_LOCAL then
  1008. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
  1009. else if objsym.bind=AB_EXTERNAL then
  1010. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
  1011. else
  1012. internalerror(2021092506);
  1013. WriteName(FWasmSymbolTable,objsym.Name);
  1014. if objsym.bind<>AB_EXTERNAL then
  1015. begin
  1016. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).SegIdx);
  1017. WriteUleb(FWasmSymbolTable,objsym.offset);
  1018. WriteUleb(FWasmSymbolTable,objsym.size);
  1019. end;
  1020. end;
  1021. end;
  1022. DoRelocations;
  1023. WriteUleb(FWasmSections[wsiCode],functions_count);
  1024. for i:=0 to Data.ObjSymbolList.Count-1 do
  1025. begin
  1026. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1027. if objsym.typ=AT_FUNCTION then
  1028. WriteFunctionCode(FWasmSections[wsiCode],objsym);
  1029. end;
  1030. WriteRelocations;
  1031. WriteSymbolTable;
  1032. WriteLinkingSubsection(WASM_SYMBOL_TABLE);
  1033. WriteLinkingSubsection(WASM_SEGMENT_INFO);
  1034. WriteRelocationCodeTable(4); { code section is section #4 }
  1035. WriteRelocationDataTable(5); { code section is section #5 }
  1036. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  1037. Writer.write(WasmVersion,SizeOf(WasmVersion));
  1038. WriteWasmSection(wsiType); { section #0 }
  1039. WriteWasmSection(wsiImport); { section #1 }
  1040. WriteWasmSection(wsiFunction); { section #2 }
  1041. WriteWasmSection(wsiDataCount); { section #3 }
  1042. WriteWasmSection(wsiCode); { section #4 }
  1043. WriteWasmSection(wsiData); { section #5 }
  1044. WriteWasmCustomSection(wcstLinking); { section #6 }
  1045. WriteWasmCustomSection(wcstRelocCode); { section #7 }
  1046. WriteWasmCustomSection(wcstRelocData); { section #8 }
  1047. Writeln('ObjSymbolList:');
  1048. for i:=0 to Data.ObjSymbolList.Count-1 do
  1049. begin
  1050. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1051. Write(objsym.Name, ' bind=', objsym.Bind, ' typ=', objsym.typ, ' address=', objsym.address, ' objsection=');
  1052. if assigned(objsym.objsection) then
  1053. Write(objsym.objsection.Name)
  1054. else
  1055. Write('nil');
  1056. Writeln;
  1057. end;
  1058. Writeln('ObjSectionList:');
  1059. for i:=0 to Data.ObjSectionList.Count-1 do
  1060. begin
  1061. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1062. Writeln(objsec.Name, ' IsCode=', objsec.IsCode, ' IsData=', objsec.IsData, ' Size=', objsec.Size, ' MemPos=', objsec.MemPos, ' DataPos=', objsec.DataPos, ' SegIdx=', objsec.SegIdx);
  1063. end;
  1064. result:=true;
  1065. end;
  1066. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  1067. var
  1068. i: TWasmSectionID;
  1069. j: TWasmCustomSectionType;
  1070. k: TWasmLinkingSubsectionType;
  1071. begin
  1072. inherited;
  1073. cobjdata:=TWasmObjData;
  1074. for i in TWasmSectionID do
  1075. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  1076. for j in TWasmCustomSectionType do
  1077. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  1078. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  1079. FWasmLinkingSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  1080. FWasmSymbolTable:=tdynamicarray.create(SectionDataMaxGrow);
  1081. FWasmSymbolTableEntriesCount:=0;
  1082. FWasmRelocationCodeTable:=tdynamicarray.create(SectionDataMaxGrow);
  1083. FWasmRelocationCodeTableEntriesCount:=0;
  1084. FWasmRelocationDataTable:=tdynamicarray.create(SectionDataMaxGrow);
  1085. FWasmRelocationDataTableEntriesCount:=0;
  1086. end;
  1087. destructor TWasmObjOutput.destroy;
  1088. var
  1089. i: TWasmSectionID;
  1090. j: TWasmCustomSectionType;
  1091. k: TWasmLinkingSubsectionType;
  1092. begin
  1093. for i in TWasmSectionID do
  1094. FWasmSections[i].Free;
  1095. for j in TWasmCustomSectionType do
  1096. FWasmCustomSections[j].Free;
  1097. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  1098. FWasmLinkingSubsections[k].Free;
  1099. FWasmSymbolTable.Free;
  1100. FWasmRelocationCodeTable.Free;
  1101. FWasmRelocationDataTable.Free;
  1102. inherited destroy;
  1103. end;
  1104. {****************************************************************************
  1105. TWasmAssembler
  1106. ****************************************************************************}
  1107. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  1108. begin
  1109. inherited;
  1110. CObjOutput:=TWasmObjOutput;
  1111. end;
  1112. {*****************************************************************************
  1113. Initialize
  1114. *****************************************************************************}
  1115. {$ifdef wasm32}
  1116. const
  1117. as_wasm32_wasm_info : tasminfo =
  1118. (
  1119. id : as_wasm32_wasm;
  1120. idtxt : 'OMF';
  1121. asmbin : '';
  1122. asmcmd : '';
  1123. supported_targets : [system_wasm32_embedded,system_wasm32_wasi];
  1124. flags : [af_outputbinary,af_smartlink_sections];
  1125. labelprefix : '..@';
  1126. labelmaxlen : -1;
  1127. comment : '; ';
  1128. dollarsign: '$';
  1129. );
  1130. {$endif wasm32}
  1131. initialization
  1132. {$ifdef wasm32}
  1133. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  1134. {$endif wasm32}
  1135. end.