ogwasm.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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. { TWasmObjSymbolExtraData }
  34. TWasmObjSymbolExtraData = class(TFPHashObject)
  35. TypeIdx: Integer;
  36. ImportModule: string;
  37. ImportName: string;
  38. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  39. end;
  40. { TWasmObjSection }
  41. TWasmObjSection = class(TObjSection)
  42. public
  43. SegIdx: Integer;
  44. SegOfs: qword;
  45. function IsCode: Boolean;
  46. function IsData: Boolean;
  47. end;
  48. { TWasmObjData }
  49. TWasmObjData = class(TObjData)
  50. private
  51. FFuncTypes: array of TWasmFuncType;
  52. FObjSymbolsExtraDataList: TFPHashObjectList;
  53. function is_smart_section(atype:TAsmSectiontype):boolean;
  54. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  55. public
  56. constructor create(const n:string);override;
  57. destructor destroy; override;
  58. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  59. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  60. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  61. function AddFuncType(wft: TWasmFuncType): integer;
  62. procedure DeclareFuncType(ft: tai_functype);
  63. procedure DeclareImportModule(aim: tai_import_module);
  64. procedure DeclareImportName(ain: tai_import_name);
  65. end;
  66. { TWasmObjOutput }
  67. TWasmObjOutput = class(tObjOutput)
  68. private
  69. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  70. procedure WriteUleb(d: tdynamicarray; v: uint64);
  71. procedure WriteUleb(w: TObjectWriter; v: uint64);
  72. procedure WriteSleb(d: tdynamicarray; v: int64);
  73. procedure WriteByte(d: tdynamicarray; b: byte);
  74. procedure WriteName(d: tdynamicarray; const s: string);
  75. procedure WriteWasmSection(wsid: TWasmSectionID);
  76. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  77. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  78. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  79. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  80. function IsExternalFunction(sym: TObjSymbol): Boolean;
  81. protected
  82. function writeData(Data:TObjData):boolean;override;
  83. public
  84. constructor create(AWriter:TObjectWriter);override;
  85. destructor destroy;override;
  86. end;
  87. { TWasmAssembler }
  88. TWasmAssembler = class(tinternalassembler)
  89. constructor create(info: pasminfo; smart:boolean);override;
  90. end;
  91. implementation
  92. uses
  93. verbose;
  94. {****************************************************************************
  95. TWasmObjSymbolExtraData
  96. ****************************************************************************}
  97. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  98. begin
  99. inherited Create(HashObjectList,s);
  100. TypeIdx:=-1;
  101. end;
  102. {****************************************************************************
  103. TWasmObjSection
  104. ****************************************************************************}
  105. function TWasmObjSection.IsCode: Boolean;
  106. const
  107. CodePrefix = '.text';
  108. begin
  109. result:=(Length(Name)>=Length(CodePrefix)) and
  110. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  111. end;
  112. function TWasmObjSection.IsData: Boolean;
  113. begin
  114. result:=not IsCode;
  115. end;
  116. {****************************************************************************
  117. TWasmObjData
  118. ****************************************************************************}
  119. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  120. begin
  121. { For bss we need to set some flags that are target dependent,
  122. it is easier to disable it for smartlinking. It doesn't take up
  123. filespace }
  124. result:=not(target_info.system in systems_darwin) and
  125. create_smartlink_sections and
  126. (atype<>sec_toc) and
  127. (atype<>sec_user) and
  128. { on embedded systems every byte counts, so smartlink bss too }
  129. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  130. end;
  131. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  132. const aname: string; aorder: TAsmSectionOrder): string;
  133. const
  134. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  135. '.text',
  136. '.data',
  137. { why doesn't .rodata work? (FK) }
  138. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  139. { vtables (and anything else containing relocations), otherwise those are }
  140. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  141. { vtable for a class called Window: }
  142. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  143. { TODO: .data.ro not yet working}
  144. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  145. '.rodata',
  146. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  147. '.data',
  148. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  149. '.rodata',
  150. '.bss',
  151. '.threadvar',
  152. '.pdata',
  153. '', { stubs }
  154. '__DATA,__nl_symbol_ptr',
  155. '__DATA,__la_symbol_ptr',
  156. '__DATA,__mod_init_func',
  157. '__DATA,__mod_term_func',
  158. '.stab',
  159. '.stabstr',
  160. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  161. '.eh_frame',
  162. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  163. '.fpc',
  164. '.toc',
  165. '.init',
  166. '.fini',
  167. '.objc_class',
  168. '.objc_meta_class',
  169. '.objc_cat_cls_meth',
  170. '.objc_cat_inst_meth',
  171. '.objc_protocol',
  172. '.objc_string_object',
  173. '.objc_cls_meth',
  174. '.objc_inst_meth',
  175. '.objc_cls_refs',
  176. '.objc_message_refs',
  177. '.objc_symbols',
  178. '.objc_category',
  179. '.objc_class_vars',
  180. '.objc_instance_vars',
  181. '.objc_module_info',
  182. '.objc_class_names',
  183. '.objc_meth_var_types',
  184. '.objc_meth_var_names',
  185. '.objc_selector_strs',
  186. '.objc_protocol_ext',
  187. '.objc_class_ext',
  188. '.objc_property',
  189. '.objc_image_info',
  190. '.objc_cstring_object',
  191. '.objc_sel_fixup',
  192. '__DATA,__objc_data',
  193. '__DATA,__objc_const',
  194. '.objc_superrefs',
  195. '__DATA, __datacoal_nt,coalesced',
  196. '.objc_classlist',
  197. '.objc_nlclasslist',
  198. '.objc_catlist',
  199. '.obcj_nlcatlist',
  200. '.objc_protolist',
  201. '.stack',
  202. '.heap',
  203. '.gcc_except_table',
  204. '.ARM.attributes'
  205. );
  206. var
  207. sep : string[3];
  208. secname : string;
  209. begin
  210. secname:=secnames[atype];
  211. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  212. begin
  213. result:=secname+'.'+aname;
  214. exit;
  215. end;
  216. if atype=sec_threadvar then
  217. begin
  218. if (target_info.system in (systems_windows+systems_wince)) then
  219. secname:='.tls'
  220. else if (target_info.system in systems_linux) then
  221. secname:='.tbss';
  222. end;
  223. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  224. Thus, data which normally goes into .rodata and .rodata_norel sections must
  225. end up in .data section }
  226. if (atype in [sec_rodata,sec_rodata_norel]) and
  227. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  228. secname:='.data';
  229. { Windows correctly handles reallocations in readonly sections }
  230. if (atype=sec_rodata) and
  231. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  232. secname:='.rodata';
  233. { section type user gives the user full controll on the section name }
  234. if atype=sec_user then
  235. secname:=aname;
  236. if is_smart_section(atype) and (aname<>'') then
  237. begin
  238. case aorder of
  239. secorder_begin :
  240. sep:='.b_';
  241. secorder_end :
  242. sep:='.z_';
  243. else
  244. sep:='.n_';
  245. end;
  246. result:=secname+sep+aname
  247. end
  248. else
  249. result:=secname;
  250. end;
  251. constructor TWasmObjData.create(const n: string);
  252. begin
  253. inherited;
  254. CObjSection:=TWasmObjSection;
  255. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  256. end;
  257. destructor TWasmObjData.destroy;
  258. var
  259. i: Integer;
  260. begin
  261. FObjSymbolsExtraDataList.Free;
  262. for i:=low(FFuncTypes) to high(FFuncTypes) do
  263. begin
  264. FFuncTypes[i].free;
  265. FFuncTypes[i]:=nil;
  266. end;
  267. inherited destroy;
  268. end;
  269. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  270. const aname: string; aorder: TAsmSectionOrder): string;
  271. begin
  272. if (atype=sec_fpc) or (atype=sec_threadvar) then
  273. atype:=sec_data;
  274. Result:=sectionname_gas(atype, aname, aorder);
  275. end;
  276. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  277. p: TObjSymbol; Reloctype: TObjRelocationType);
  278. begin
  279. end;
  280. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  281. begin
  282. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  283. if not assigned(result) then
  284. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  285. end;
  286. function TWasmObjData.AddFuncType(wft: TWasmFuncType): integer;
  287. var
  288. i: Integer;
  289. begin
  290. for i:=low(FFuncTypes) to high(FFuncTypes) do
  291. if wft.Equals(FFuncTypes[i]) then
  292. exit(i);
  293. result:=Length(FFuncTypes);
  294. SetLength(FFuncTypes,result+1);
  295. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  296. end;
  297. procedure TWasmObjData.DeclareFuncType(ft: tai_functype);
  298. var
  299. i: Integer;
  300. ObjSymExtraData: TWasmObjSymbolExtraData;
  301. begin
  302. i:=AddFuncType(ft.functype);
  303. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  304. ObjSymExtraData.TypeIdx:=i;
  305. end;
  306. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  307. var
  308. ObjSymExtraData: TWasmObjSymbolExtraData;
  309. begin
  310. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  311. ObjSymExtraData.ImportModule:=aim.importmodule;
  312. end;
  313. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  314. var
  315. ObjSymExtraData: TWasmObjSymbolExtraData;
  316. begin
  317. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  318. ObjSymExtraData.ImportName:=ain.importname;
  319. end;
  320. {****************************************************************************
  321. TWasmObjOutput
  322. ****************************************************************************}
  323. procedure TWasmObjOutput.WriteUleb(d: tdynamicarray; v: uint64);
  324. var
  325. b: byte;
  326. begin
  327. repeat
  328. b:=byte(v) and 127;
  329. v:=v shr 7;
  330. if v<>0 then
  331. b:=b or 128;
  332. d.write(b,1);
  333. until v=0;
  334. end;
  335. procedure TWasmObjOutput.WriteUleb(w: TObjectWriter; v: uint64);
  336. var
  337. b: byte;
  338. begin
  339. repeat
  340. b:=byte(v) and 127;
  341. v:=v shr 7;
  342. if v<>0 then
  343. b:=b or 128;
  344. w.write(b,1);
  345. until v=0;
  346. end;
  347. procedure TWasmObjOutput.WriteSleb(d: tdynamicarray; v: int64);
  348. var
  349. b: byte;
  350. Done: Boolean=false;
  351. begin
  352. repeat
  353. b:=byte(v) and 127;
  354. v:=SarInt64(v,7);
  355. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  356. Done:=true
  357. else
  358. b:=b or 128;
  359. d.write(b,1);
  360. until Done;
  361. end;
  362. procedure TWasmObjOutput.WriteByte(d: tdynamicarray; b: byte);
  363. begin
  364. d.write(b,1);
  365. end;
  366. procedure TWasmObjOutput.WriteName(d: tdynamicarray; const s: string);
  367. begin
  368. WriteUleb(d,Length(s));
  369. d.writestr(s);
  370. end;
  371. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  372. var
  373. b: byte;
  374. begin
  375. b:=ord(wsid);
  376. Writer.write(b,1);
  377. WriteUleb(Writer,FWasmSections[wsid].size);
  378. Writer.writearray(FWasmSections[wsid]);
  379. end;
  380. procedure TWasmObjOutput.CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  381. var
  382. buf: array [0..4095] of byte;
  383. bs: Integer;
  384. begin
  385. while size>0 do
  386. begin
  387. if size<SizeOf(buf) then
  388. bs:=Integer(size)
  389. else
  390. bs:=SizeOf(buf);
  391. src.read(buf,bs);
  392. dest.write(buf,bs);
  393. dec(size,bs);
  394. end;
  395. end;
  396. procedure TWasmObjOutput.WriteZeros(dest: tdynamicarray; size: QWord);
  397. var
  398. buf : array[0..1023] of byte;
  399. bs: Integer;
  400. begin
  401. fillchar(buf,sizeof(buf),0);
  402. while size>0 do
  403. begin
  404. if size<SizeOf(buf) then
  405. bs:=Integer(size)
  406. else
  407. bs:=SizeOf(buf);
  408. dest.write(buf,bs);
  409. dec(size,bs);
  410. end;
  411. end;
  412. procedure TWasmObjOutput.WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  413. var
  414. i: Integer;
  415. begin
  416. WriteUleb(dest,Length(wrt));
  417. for i:=low(wrt) to high(wrt) do
  418. WriteWasmBasicType(dest,wrt[i]);
  419. end;
  420. procedure TWasmObjOutput.WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  421. begin
  422. case wbt of
  423. wbt_i32:
  424. WriteByte(dest,$7F);
  425. wbt_i64:
  426. WriteByte(dest,$7E);
  427. wbt_f32:
  428. WriteByte(dest,$7D);
  429. wbt_f64:
  430. WriteByte(dest,$7C);
  431. end;
  432. end;
  433. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  434. begin
  435. result:=(sym.bind=AB_EXTERNAL) and (TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name)<>nil);
  436. end;
  437. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  438. var
  439. i: Integer;
  440. objsec: TWasmObjSection;
  441. segment_count: Integer = 0;
  442. cur_seg_ofs: qword = 0;
  443. types_count,
  444. imports_count: Integer;
  445. import_functions_count: Integer = 0;
  446. objsym: TObjSymbol;
  447. begin
  448. for i:=0 to Data.ObjSymbolList.Count-1 do
  449. begin
  450. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  451. if IsExternalFunction(objsym) then
  452. Inc(import_functions_count);
  453. end;
  454. types_count:=Length(TWasmObjData(Data).FFuncTypes);
  455. WriteUleb(FWasmSections[wsiType],types_count);
  456. for i:=0 to types_count-1 do
  457. with TWasmObjData(Data).FFuncTypes[i] do
  458. begin
  459. WriteByte(FWasmSections[wsiType],$60);
  460. WriteWasmResultType(FWasmSections[wsiType],params);
  461. WriteWasmResultType(FWasmSections[wsiType],results);
  462. end;
  463. for i:=0 to Data.ObjSectionList.Count-1 do
  464. begin
  465. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  466. if objsec.IsCode then
  467. objsec.SegIdx:=-1
  468. else
  469. begin
  470. objsec.SegIdx:=segment_count;
  471. objsec.SegOfs:=cur_seg_ofs;
  472. Inc(segment_count);
  473. Inc(cur_seg_ofs,objsec.Size);
  474. end;
  475. end;
  476. WriteUleb(FWasmSections[wsiData],segment_count);
  477. for i:=0 to Data.ObjSectionList.Count-1 do
  478. begin
  479. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  480. if objsec.IsData then
  481. begin
  482. WriteByte(FWasmSections[wsiData],0);
  483. WriteByte(FWasmSections[wsiData],$41);
  484. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  485. WriteByte(FWasmSections[wsiData],$0b);
  486. WriteUleb(FWasmSections[wsiData],objsec.Size);
  487. if oso_Data in objsec.SecOptions then
  488. begin
  489. objsec.Data.seek(0);
  490. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  491. end
  492. else
  493. begin
  494. WriteZeros(FWasmSections[wsiData],objsec.Size);
  495. end;
  496. end;
  497. end;
  498. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  499. imports_count:=3+import_functions_count;
  500. WriteUleb(FWasmSections[wsiImport],imports_count);
  501. { import[0] }
  502. WriteName(FWasmSections[wsiImport],'env');
  503. WriteName(FWasmSections[wsiImport],'__linear_memory');
  504. WriteByte(FWasmSections[wsiImport],$02); { mem }
  505. WriteByte(FWasmSections[wsiImport],$00); { min }
  506. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  507. { import[1] }
  508. WriteName(FWasmSections[wsiImport],'env');
  509. WriteName(FWasmSections[wsiImport],'__stack_pointer');
  510. WriteByte(FWasmSections[wsiImport],$03); { global }
  511. WriteByte(FWasmSections[wsiImport],$7F); { i32 }
  512. WriteByte(FWasmSections[wsiImport],$01); { var }
  513. { import[2]..import[imports_count-2] }
  514. for i:=0 to Data.ObjSymbolList.Count-1 do
  515. begin
  516. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  517. if IsExternalFunction(objsym) then
  518. begin
  519. WriteName(FWasmSections[wsiImport],'env');
  520. WriteName(FWasmSections[wsiImport],objsym.Name);
  521. WriteByte(FWasmSections[wsiImport],$00); { func }
  522. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(TWasmObjData(Data).FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  523. end;
  524. end;
  525. { import[imports_count-1] }
  526. WriteName(FWasmSections[wsiImport],'env');
  527. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  528. WriteByte(FWasmSections[wsiImport],$01); { table }
  529. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  530. WriteByte(FWasmSections[wsiImport],$00); { min }
  531. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  532. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  533. Writer.write(WasmVersion,SizeOf(WasmVersion));
  534. WriteWasmSection(wsiType);
  535. WriteWasmSection(wsiImport);
  536. WriteWasmSection(wsiDataCount);
  537. WriteWasmSection(wsiData);
  538. Writeln('ObjSymbolList:');
  539. for i:=0 to Data.ObjSymbolList.Count-1 do
  540. begin
  541. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  542. Write(objsym.Name, ' bind=', objsym.Bind, ' typ=', objsym.typ, ' address=', objsym.address, ' objsection=');
  543. if assigned(objsym.objsection) then
  544. Write(objsym.objsection.Name)
  545. else
  546. Write('nil');
  547. Writeln;
  548. end;
  549. Writeln('ObjSectionList:');
  550. for i:=0 to Data.ObjSectionList.Count-1 do
  551. begin
  552. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  553. Writeln(objsec.Name, ' IsCode=', objsec.IsCode, ' IsData=', objsec.IsData, ' Size=', objsec.Size, ' MemPos=', objsec.MemPos, ' DataPos=', objsec.DataPos, ' SegIdx=', objsec.SegIdx);
  554. end;
  555. result:=true;
  556. end;
  557. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  558. var
  559. i: TWasmSectionID;
  560. begin
  561. inherited;
  562. cobjdata:=TWasmObjData;
  563. for i in TWasmSectionID do
  564. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  565. end;
  566. destructor TWasmObjOutput.destroy;
  567. var
  568. i: TWasmSectionID;
  569. begin
  570. for i in TWasmSectionID do
  571. FWasmSections[i].Free;
  572. inherited destroy;
  573. end;
  574. {****************************************************************************
  575. TWasmAssembler
  576. ****************************************************************************}
  577. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  578. begin
  579. inherited;
  580. CObjOutput:=TWasmObjOutput;
  581. end;
  582. {*****************************************************************************
  583. Initialize
  584. *****************************************************************************}
  585. {$ifdef wasm32}
  586. const
  587. as_wasm32_wasm_info : tasminfo =
  588. (
  589. id : as_wasm32_wasm;
  590. idtxt : 'OMF';
  591. asmbin : '';
  592. asmcmd : '';
  593. supported_targets : [system_wasm32_embedded,system_wasm32_wasi];
  594. flags : [af_outputbinary,af_smartlink_sections];
  595. labelprefix : '..@';
  596. labelmaxlen : -1;
  597. comment : '; ';
  598. dollarsign: '$';
  599. );
  600. {$endif wasm32}
  601. initialization
  602. {$ifdef wasm32}
  603. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  604. {$endif wasm32}
  605. end.