ogwasm.pas 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473
  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 = class;
  34. { TWasmObjSymbol }
  35. TWasmObjSymbol = class(TObjSymbol)
  36. FuncIndex: Integer;
  37. SymbolIndex: Integer;
  38. GlobalIndex: Integer;
  39. TagIndex: Integer;
  40. AliasOf: string;
  41. ExtraData: TWasmObjSymbolExtraData;
  42. constructor create(AList:TFPHashObjectList;const AName:string);override;
  43. function IsAlias: Boolean;
  44. end;
  45. { TWasmObjRelocation }
  46. TWasmObjRelocation = class(TObjRelocation)
  47. public
  48. TypeIndex: Integer;
  49. Addend: LongInt;
  50. constructor CreateTypeIndex(ADataOffset:TObjSectionOfs; ATypeIndex: Integer);
  51. end;
  52. { TWasmObjSymbolExtraData }
  53. TWasmObjSymbolExtraData = class(TFPHashObject)
  54. TypeIdx: Integer;
  55. ExceptionTagTypeIdx: Integer;
  56. ImportModule: string;
  57. ImportName: string;
  58. ExportName: string;
  59. GlobalType: TWasmBasicType;
  60. GlobalIsImmutable: Boolean;
  61. Locals: array of TWasmBasicType;
  62. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  63. procedure AddLocal(bastyp: TWasmBasicType);
  64. end;
  65. { TWasmObjSection }
  66. TWasmObjSection = class(TObjSection)
  67. public
  68. SegIdx: Integer;
  69. SegSymIdx: Integer;
  70. SegOfs: qword;
  71. FileSectionOfs: qword;
  72. MainFuncSymbol: TWasmObjSymbol;
  73. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  74. function IsCode: Boolean;
  75. function IsData: Boolean;
  76. function IsDebug: Boolean;
  77. end;
  78. { TWasmObjData }
  79. TWasmObjData = class(TObjData)
  80. private
  81. FFuncTypes: array of TWasmFuncType;
  82. FObjSymbolsExtraDataList: TFPHashObjectList;
  83. FLastFuncName: string;
  84. function is_smart_section(atype:TAsmSectiontype):boolean;
  85. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  86. public
  87. constructor create(const n:string);override;
  88. destructor destroy; override;
  89. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  90. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  91. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  92. function AddFuncType(wft: TWasmFuncType): integer;
  93. function globalref(asmsym:TAsmSymbol):TObjSymbol;
  94. function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
  95. procedure DeclareGlobalType(gt: tai_globaltype);
  96. procedure DeclareFuncType(ft: tai_functype);
  97. procedure DeclareTagType(tt: tai_tagtype);
  98. procedure DeclareExportName(en: tai_export_name);
  99. procedure DeclareImportModule(aim: tai_import_module);
  100. procedure DeclareImportName(ain: tai_import_name);
  101. procedure DeclareLocal(al: tai_local);
  102. procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);override;
  103. end;
  104. { TWasmObjOutput }
  105. TWasmObjOutput = class(tObjOutput)
  106. private
  107. FData: TWasmObjData;
  108. FWasmRelocationCodeTable: tdynamicarray;
  109. FWasmRelocationCodeTableEntriesCount: Integer;
  110. FWasmRelocationDataTable: tdynamicarray;
  111. FWasmRelocationDataTableEntriesCount: Integer;
  112. FWasmRelocationDebugFrameTable: tdynamicarray;
  113. FWasmRelocationDebugFrameTableEntriesCount: Integer;
  114. FWasmRelocationDebugInfoTable: tdynamicarray;
  115. FWasmRelocationDebugInfoTableEntriesCount: Integer;
  116. FWasmRelocationDebugLineTable: tdynamicarray;
  117. FWasmRelocationDebugLineTableEntriesCount: Integer;
  118. FWasmRelocationDebugAbbrevTable: tdynamicarray;
  119. FWasmRelocationDebugAbbrevTableEntriesCount: Integer;
  120. FWasmRelocationDebugArangesTable: tdynamicarray;
  121. FWasmRelocationDebugArangesTableEntriesCount: Integer;
  122. FWasmRelocationDebugRangesTable: tdynamicarray;
  123. FWasmRelocationDebugRangesTableEntriesCount: Integer;
  124. FWasmRelocationDebugStrTable: tdynamicarray;
  125. FWasmRelocationDebugStrTableEntriesCount: Integer;
  126. FWasmSymbolTable: tdynamicarray;
  127. FWasmSymbolTableEntriesCount: Integer;
  128. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  129. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  130. FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of tdynamicarray;
  131. procedure WriteUleb(d: tdynamicarray; v: uint64);
  132. procedure WriteUleb(w: TObjectWriter; v: uint64);
  133. procedure WriteSleb(d: tdynamicarray; v: int64);
  134. procedure WriteByte(d: tdynamicarray; b: byte);
  135. procedure WriteName(d: tdynamicarray; const s: string);
  136. procedure WriteWasmSection(wsid: TWasmSectionID);
  137. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  138. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  139. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  140. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  141. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  142. function IsExternalFunction(sym: TObjSymbol): Boolean;
  143. function IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  144. procedure WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
  145. procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  146. procedure WriteSymbolTable;
  147. procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
  148. procedure WriteRelocationDataTable(DataSectionIndex: Integer);
  149. procedure MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  150. procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  151. procedure DoRelocations;
  152. procedure WriteRelocations;
  153. function FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  154. protected
  155. function writeData(Data:TObjData):boolean;override;
  156. public
  157. constructor create(AWriter:TObjectWriter);override;
  158. destructor destroy;override;
  159. end;
  160. { TWasmObjInput }
  161. TWasmObjInput = class(TObjInput)
  162. private
  163. FFuncTypes: array of TWasmFuncType;
  164. function ReadUleb(r: TObjectReader; out v: uint64): boolean;
  165. public
  166. constructor create;override;
  167. destructor Destroy;override;
  168. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  169. function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
  170. end;
  171. { TWasmExeOutput }
  172. TWasmExeOutput = class(TExeOutput)
  173. protected
  174. function writeData:boolean;override;
  175. procedure DoRelocationFixup(objsec:TObjSection);override;
  176. public
  177. constructor create;override;
  178. end;
  179. { TWasmAssembler }
  180. TWasmAssembler = class(tinternalassembler)
  181. constructor create(info: pasminfo; smart:boolean);override;
  182. end;
  183. implementation
  184. uses
  185. cutils,verbose,version,globals;
  186. procedure WriteUleb5(d: tdynamicarray; v: uint64);
  187. var
  188. b: byte;
  189. i: Integer;
  190. begin
  191. for i:=1 to 5 do
  192. begin
  193. b:=byte(v) and 127;
  194. v:=v shr 7;
  195. if i<>5 then
  196. b:=b or 128;
  197. d.write(b,1);
  198. end;
  199. end;
  200. procedure WriteUleb5(d: tobjsection; v: uint64);
  201. var
  202. b: byte;
  203. i: Integer;
  204. begin
  205. for i:=1 to 5 do
  206. begin
  207. b:=byte(v) and 127;
  208. v:=v shr 7;
  209. if i<>5 then
  210. b:=b or 128;
  211. d.write(b,1);
  212. end;
  213. end;
  214. procedure WriteSleb5(d: tdynamicarray; v: int64);
  215. var
  216. b: byte;
  217. i: Integer;
  218. begin
  219. for i:=1 to 5 do
  220. begin
  221. b:=byte(v) and 127;
  222. v:=SarInt64(v,7);
  223. if i<>5 then
  224. b:=b or 128;
  225. d.write(b,1);
  226. end;
  227. end;
  228. procedure WriteSleb5(d: tobjsection; v: int64);
  229. var
  230. b: byte;
  231. i: Integer;
  232. begin
  233. for i:=1 to 5 do
  234. begin
  235. b:=byte(v) and 127;
  236. v:=SarInt64(v,7);
  237. if i<>5 then
  238. b:=b or 128;
  239. d.write(b,1);
  240. end;
  241. end;
  242. function ReadUleb(d: tdynamicarray): uint64;
  243. var
  244. b: byte;
  245. shift:integer;
  246. begin
  247. b:=0;
  248. result:=0;
  249. shift:=0;
  250. repeat
  251. d.read(b,1);
  252. result:=result or (uint64(b and 127) shl shift);
  253. inc(shift,7);
  254. until (b and 128)=0;
  255. end;
  256. function ReadSleb(d: tdynamicarray): int64;
  257. var
  258. b: byte;
  259. shift:integer;
  260. begin
  261. b:=0;
  262. result:=0;
  263. shift:=0;
  264. repeat
  265. d.read(b,1);
  266. result:=result or (uint64(b and 127) shl shift);
  267. inc(shift,7);
  268. until (b and 128)=0;
  269. {$ifopt Q+}
  270. {$define overflowon}
  271. {$Q-}
  272. {$endif}
  273. {$ifopt R+}
  274. {$define rangeon}
  275. {$R-}
  276. {$endif}
  277. if (b and 64)<>0 then
  278. result:=result or (high(uint64) shl shift);
  279. end;
  280. {$ifdef overflowon}
  281. {$Q+}
  282. {$undef overflowon}
  283. {$endif}
  284. {$ifdef rangeon}
  285. {$R+}
  286. {$undef rangeon}
  287. {$endif}
  288. procedure AddSleb5(d: tdynamicarray; v: int64);
  289. var
  290. q: Int64;
  291. p: LongWord;
  292. begin
  293. p:=d.Pos;
  294. q:=ReadSleb(d);
  295. q:=q+v;
  296. d.seek(p);
  297. WriteSleb5(d,q);
  298. end;
  299. procedure AddUleb5(d: tdynamicarray; v: int64);
  300. var
  301. q: UInt64;
  302. p: LongWord;
  303. begin
  304. p:=d.Pos;
  305. q:=ReadUleb(d);
  306. q:=q+v;
  307. d.seek(p);
  308. WriteUleb5(d,q);
  309. end;
  310. procedure AddInt32(d: tdynamicarray; v: int32);
  311. var
  312. q: int32;
  313. p: LongWord;
  314. begin
  315. p:=d.Pos;
  316. d.read(q,4);
  317. {$ifdef FPC_BIG_ENDIAN}
  318. q:=SwapEndian(q);
  319. {$endif FPC_BIG_ENDIAN}
  320. q:=q+v;
  321. {$ifdef FPC_BIG_ENDIAN}
  322. q:=SwapEndian(q);
  323. {$endif FPC_BIG_ENDIAN}
  324. d.seek(p);
  325. d.write(q,4);
  326. end;
  327. {****************************************************************************
  328. TWasmObjRelocation
  329. ****************************************************************************}
  330. constructor TWasmObjRelocation.CreateTypeIndex(ADataOffset: TObjSectionOfs; ATypeIndex: Integer);
  331. begin
  332. DataOffset:=ADataOffset;
  333. Symbol:=nil;
  334. OrgSize:=0;
  335. Group:=nil;
  336. ObjSection:=nil;
  337. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  338. TypeIndex:=ATypeIndex;
  339. end;
  340. {****************************************************************************
  341. TWasmObjSymbol
  342. ****************************************************************************}
  343. constructor TWasmObjSymbol.create(AList: TFPHashObjectList; const AName: string);
  344. begin
  345. inherited create(AList,AName);
  346. FuncIndex:=-1;
  347. SymbolIndex:=-1;
  348. GlobalIndex:=-1;
  349. TagIndex:=-1;
  350. AliasOf:='';
  351. ExtraData:=nil;
  352. end;
  353. function TWasmObjSymbol.IsAlias: Boolean;
  354. begin
  355. result:=AliasOf<>'';
  356. end;
  357. {****************************************************************************
  358. TWasmObjSymbolExtraData
  359. ****************************************************************************}
  360. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  361. begin
  362. inherited Create(HashObjectList,s);
  363. TypeIdx:=-1;
  364. ExceptionTagTypeIdx:=-1;
  365. end;
  366. procedure TWasmObjSymbolExtraData.AddLocal(bastyp: TWasmBasicType);
  367. begin
  368. SetLength(Locals,Length(Locals)+1);
  369. Locals[High(Locals)]:=bastyp;
  370. end;
  371. {****************************************************************************
  372. TWasmObjSection
  373. ****************************************************************************}
  374. constructor TWasmObjSection.create(AList: TFPHashObjectList; const Aname: string; Aalign: longint; Aoptions: TObjSectionOptions);
  375. begin
  376. inherited create(AList, Aname, Aalign, Aoptions);
  377. SegIdx:=-1;
  378. SegSymIdx:=-1;
  379. MainFuncSymbol:=nil;
  380. end;
  381. function TWasmObjSection.IsCode: Boolean;
  382. const
  383. CodePrefix = '.text';
  384. begin
  385. result:=(Length(Name)>=Length(CodePrefix)) and
  386. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  387. end;
  388. function TWasmObjSection.IsData: Boolean;
  389. begin
  390. result:=not (IsCode or IsDebug);
  391. end;
  392. function TWasmObjSection.IsDebug: Boolean;
  393. const
  394. DebugPrefix = '.debug';
  395. begin
  396. result:=(Length(Name)>=Length(DebugPrefix)) and
  397. (Copy(Name,1,Length(DebugPrefix))=DebugPrefix);
  398. end;
  399. {****************************************************************************
  400. TWasmObjData
  401. ****************************************************************************}
  402. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  403. begin
  404. { For bss we need to set some flags that are target dependent,
  405. it is easier to disable it for smartlinking. It doesn't take up
  406. filespace }
  407. result:=not(target_info.system in systems_darwin) and
  408. create_smartlink_sections and
  409. (atype<>sec_toc) and
  410. (atype<>sec_user) and
  411. { on embedded systems every byte counts, so smartlink bss too }
  412. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  413. end;
  414. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  415. const aname: string; aorder: TAsmSectionOrder): string;
  416. const
  417. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  418. '.text',
  419. '.data',
  420. { why doesn't .rodata work? (FK) }
  421. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  422. { vtables (and anything else containing relocations), otherwise those are }
  423. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  424. { vtable for a class called Window: }
  425. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  426. { TODO: .data.ro not yet working}
  427. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  428. '.rodata',
  429. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  430. '.data',
  431. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  432. '.rodata',
  433. '.bss',
  434. '.tbss',
  435. '.pdata',
  436. '', { stubs }
  437. '__DATA,__nl_symbol_ptr',
  438. '__DATA,__la_symbol_ptr',
  439. '__DATA,__mod_init_func',
  440. '__DATA,__mod_term_func',
  441. '.stab',
  442. '.stabstr',
  443. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  444. '.eh_frame',
  445. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  446. '.fpc',
  447. '.toc',
  448. '.init',
  449. '.fini',
  450. '.objc_class',
  451. '.objc_meta_class',
  452. '.objc_cat_cls_meth',
  453. '.objc_cat_inst_meth',
  454. '.objc_protocol',
  455. '.objc_string_object',
  456. '.objc_cls_meth',
  457. '.objc_inst_meth',
  458. '.objc_cls_refs',
  459. '.objc_message_refs',
  460. '.objc_symbols',
  461. '.objc_category',
  462. '.objc_class_vars',
  463. '.objc_instance_vars',
  464. '.objc_module_info',
  465. '.objc_class_names',
  466. '.objc_meth_var_types',
  467. '.objc_meth_var_names',
  468. '.objc_selector_strs',
  469. '.objc_protocol_ext',
  470. '.objc_class_ext',
  471. '.objc_property',
  472. '.objc_image_info',
  473. '.objc_cstring_object',
  474. '.objc_sel_fixup',
  475. '__DATA,__objc_data',
  476. '__DATA,__objc_const',
  477. '.objc_superrefs',
  478. '__DATA, __datacoal_nt,coalesced',
  479. '.objc_classlist',
  480. '.objc_nlclasslist',
  481. '.objc_catlist',
  482. '.obcj_nlcatlist',
  483. '.objc_protolist',
  484. '.stack',
  485. '.heap',
  486. '.gcc_except_table',
  487. '.ARM.attributes'
  488. );
  489. var
  490. sep : string[3];
  491. secname : string;
  492. begin
  493. secname:=secnames[atype];
  494. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  495. begin
  496. result:=secname+'.'+aname;
  497. exit;
  498. end;
  499. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  500. Thus, data which normally goes into .rodata and .rodata_norel sections must
  501. end up in .data section }
  502. if (atype in [sec_rodata,sec_rodata_norel]) and
  503. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  504. secname:='.data';
  505. { Windows correctly handles reallocations in readonly sections }
  506. if (atype=sec_rodata) and
  507. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  508. secname:='.rodata';
  509. { section type user gives the user full controll on the section name }
  510. if atype=sec_user then
  511. secname:=aname;
  512. if is_smart_section(atype) and (aname<>'') then
  513. begin
  514. case aorder of
  515. secorder_begin :
  516. sep:='.b_';
  517. secorder_end :
  518. sep:='.z_';
  519. else
  520. sep:='.n_';
  521. end;
  522. result:=secname+sep+aname
  523. end
  524. else
  525. result:=secname;
  526. end;
  527. constructor TWasmObjData.create(const n: string);
  528. begin
  529. inherited;
  530. CObjSection:=TWasmObjSection;
  531. CObjSymbol:=TWasmObjSymbol;
  532. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  533. end;
  534. destructor TWasmObjData.destroy;
  535. var
  536. i: Integer;
  537. begin
  538. FObjSymbolsExtraDataList.Free;
  539. for i:=low(FFuncTypes) to high(FFuncTypes) do
  540. begin
  541. FFuncTypes[i].free;
  542. FFuncTypes[i]:=nil;
  543. end;
  544. inherited destroy;
  545. end;
  546. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  547. const aname: string; aorder: TAsmSectionOrder): string;
  548. begin
  549. if (atype=sec_fpc) or
  550. ((atype=sec_threadvar) and not (ts_wasm_threads in current_settings.targetswitches)) then
  551. atype:=sec_data;
  552. Result:=sectionname_gas(atype, aname, aorder);
  553. end;
  554. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  555. p: TObjSymbol; Reloctype: TObjRelocationType);
  556. const
  557. leb_zero: array[0..4] of byte=($80,$80,$80,$80,$00);
  558. var
  559. objreloc: TWasmObjRelocation;
  560. begin
  561. if CurrObjSec=nil then
  562. internalerror(200403072);
  563. { workaround crash, when generating debug info for threadvars, when multithreading is turned off.
  564. todo: ensure the debug info for threadvars is actually correct, once we've got WebAssembly debug info working in general }
  565. if (Reloctype=RELOC_DTPOFF) and not (ts_wasm_threads in current_settings.targetswitches) then
  566. Reloctype:=RELOC_ABSOLUTE;
  567. objreloc:=nil;
  568. case Reloctype of
  569. RELOC_FUNCTION_INDEX_LEB:
  570. begin
  571. if Data<>0 then
  572. internalerror(2021092502);
  573. if len<>5 then
  574. internalerror(2021092503);
  575. if not assigned(p) then
  576. internalerror(2021092504);
  577. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  578. CurrObjSec.ObjRelocations.Add(objreloc);
  579. writebytes(leb_zero,5);
  580. end;
  581. RELOC_MEMORY_ADDR_LEB,
  582. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  583. begin
  584. if (Reloctype=RELOC_MEMORY_ADDR_LEB) and (Data<0) then
  585. internalerror(2021092602);
  586. if len<>5 then
  587. internalerror(2021092503);
  588. if not assigned(p) then
  589. internalerror(2021092504);
  590. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  591. objreloc.Addend:=Data;
  592. CurrObjSec.ObjRelocations.Add(objreloc);
  593. if RelocType=RELOC_MEMORY_ADDR_LEB then
  594. WriteUleb5(CurrObjSec,Data)
  595. else
  596. WriteSleb5(CurrObjSec,Data);
  597. end;
  598. RELOC_ABSOLUTE:
  599. begin
  600. if len<>4 then
  601. internalerror(2021092607);
  602. if not assigned(p) then
  603. internalerror(2021092608);
  604. if (p.objsection<>nil) and TWasmObjSection(p.objsection).IsDebug and
  605. (p.bind<>AB_COMMON) and (p.bind<>AB_EXTERNAL) then
  606. begin
  607. objreloc:=TWasmObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,RELOC_ABSOLUTE);
  608. objreloc.Addend:=Data+p.Address;
  609. CurrObjSec.ObjRelocations.Add(objreloc);
  610. {inc(data,p.address);}
  611. data:=0;
  612. Data:=NtoLE(Data);
  613. writebytes(Data,4);
  614. end
  615. else
  616. begin
  617. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  618. objreloc.Addend:=Data;
  619. CurrObjSec.ObjRelocations.Add(objreloc);
  620. Data:=NtoLE(Data);
  621. writebytes(Data,4);
  622. end;
  623. end;
  624. RELOC_TYPE_INDEX_LEB:
  625. begin
  626. if len<>5 then
  627. internalerror(2021092612);
  628. if assigned(p) then
  629. internalerror(2021092613);
  630. objreloc:=TWasmObjRelocation.CreateTypeIndex(CurrObjSec.Size,Data);
  631. CurrObjSec.ObjRelocations.Add(objreloc);
  632. WriteUleb5(CurrObjSec,Data);
  633. end;
  634. RELOC_GLOBAL_INDEX_LEB:
  635. begin
  636. if len<>5 then
  637. internalerror(2021092701);
  638. if Data<>0 then
  639. internalerror(2021092702);
  640. if not assigned(p) then
  641. internalerror(2021092703);
  642. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  643. CurrObjSec.ObjRelocations.Add(objreloc);
  644. WriteUleb5(CurrObjSec,0);
  645. end;
  646. RELOC_TAG_INDEX_LEB:
  647. begin
  648. if len<>5 then
  649. internalerror(2021092712);
  650. if Data<>0 then
  651. internalerror(2021092713);
  652. if not assigned(p) then
  653. internalerror(2021092714);
  654. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  655. CurrObjSec.ObjRelocations.Add(objreloc);
  656. WriteSleb5(CurrObjSec,0);
  657. end;
  658. else
  659. internalerror(2021092501);
  660. end;
  661. end;
  662. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  663. begin
  664. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  665. if not assigned(result) then
  666. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  667. end;
  668. function TWasmObjData.AddFuncType(wft: TWasmFuncType): integer;
  669. var
  670. i: Integer;
  671. begin
  672. for i:=low(FFuncTypes) to high(FFuncTypes) do
  673. if wft.Equals(FFuncTypes[i]) then
  674. exit(i);
  675. result:=Length(FFuncTypes);
  676. SetLength(FFuncTypes,result+1);
  677. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  678. end;
  679. function TWasmObjData.globalref(asmsym: TAsmSymbol): TObjSymbol;
  680. begin
  681. if assigned(asmsym) then
  682. begin
  683. if (asmsym.typ<>AT_WASM_GLOBAL) and (asmsym.typ<>AT_TLS) then
  684. internalerror(2021092706);
  685. result:=symbolref(asmsym);
  686. result.typ:=asmsym.typ;
  687. end
  688. else
  689. result:=nil;
  690. end;
  691. function TWasmObjData.ExceptionTagRef(asmsym: TAsmSymbol): TObjSymbol;
  692. begin
  693. if assigned(asmsym) then
  694. begin
  695. if asmsym.typ<>AT_WASM_EXCEPTION_TAG then
  696. internalerror(2021092707);
  697. result:=symbolref(asmsym);
  698. result.typ:=AT_WASM_EXCEPTION_TAG;
  699. end
  700. else
  701. result:=nil;
  702. end;
  703. procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
  704. var
  705. ObjSymExtraData: TWasmObjSymbolExtraData;
  706. ObjSym: TObjSymbol;
  707. begin
  708. if not gt.is_external then
  709. begin
  710. ObjSym:=symboldefine(gt.sym);
  711. ObjSym.typ:=AT_WASM_GLOBAL;
  712. end;
  713. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(gt.globalname);
  714. ObjSymExtraData.GlobalType:=gt.gtype;
  715. ObjSymExtraData.GlobalIsImmutable:=gt.immutable;
  716. end;
  717. procedure TWasmObjData.DeclareFuncType(ft: tai_functype);
  718. var
  719. i: Integer;
  720. ObjSymExtraData: TWasmObjSymbolExtraData;
  721. begin
  722. FLastFuncName:=ft.funcname;
  723. i:=AddFuncType(ft.functype);
  724. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  725. ObjSymExtraData.TypeIdx:=i;
  726. end;
  727. procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
  728. var
  729. ObjSymExtraData: TWasmObjSymbolExtraData;
  730. ft: TWasmFuncType;
  731. i: Integer;
  732. begin
  733. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(tt.tagname);
  734. ft:=TWasmFuncType.Create([],tt.params);
  735. i:=AddFuncType(ft);
  736. ft.free;
  737. ObjSymExtraData.ExceptionTagTypeIdx:=i;
  738. end;
  739. procedure TWasmObjData.DeclareExportName(en: tai_export_name);
  740. var
  741. ObjSymExtraData: TWasmObjSymbolExtraData;
  742. begin
  743. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(en.intname);
  744. ObjSymExtraData.ExportName:=en.extname;
  745. end;
  746. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  747. var
  748. ObjSymExtraData: TWasmObjSymbolExtraData;
  749. begin
  750. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  751. ObjSymExtraData.ImportModule:=aim.importmodule;
  752. end;
  753. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  754. var
  755. ObjSymExtraData: TWasmObjSymbolExtraData;
  756. begin
  757. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  758. ObjSymExtraData.ImportName:=ain.importname;
  759. end;
  760. procedure TWasmObjData.DeclareLocal(al: tai_local);
  761. var
  762. ObjSymExtraData: TWasmObjSymbolExtraData;
  763. begin
  764. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  765. ObjSymExtraData.AddLocal(al.bastyp);
  766. end;
  767. procedure TWasmObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
  768. var
  769. valsym: TObjSymbol;
  770. aliassym: TWasmObjSymbol;
  771. begin
  772. valsym:=CreateSymbol(avalue);
  773. aliassym:=TWasmObjSymbol(symboldefine(asym,valsym.bind,valsym.typ));
  774. aliassym.AliasOf:=valsym.Name;
  775. end;
  776. {****************************************************************************
  777. TWasmObjOutput
  778. ****************************************************************************}
  779. procedure TWasmObjOutput.WriteUleb(d: tdynamicarray; v: uint64);
  780. var
  781. b: byte;
  782. begin
  783. repeat
  784. b:=byte(v) and 127;
  785. v:=v shr 7;
  786. if v<>0 then
  787. b:=b or 128;
  788. d.write(b,1);
  789. until v=0;
  790. end;
  791. procedure TWasmObjOutput.WriteUleb(w: TObjectWriter; v: uint64);
  792. var
  793. b: byte;
  794. begin
  795. repeat
  796. b:=byte(v) and 127;
  797. v:=v shr 7;
  798. if v<>0 then
  799. b:=b or 128;
  800. w.write(b,1);
  801. until v=0;
  802. end;
  803. procedure TWasmObjOutput.WriteSleb(d: tdynamicarray; v: int64);
  804. var
  805. b: byte;
  806. Done: Boolean=false;
  807. begin
  808. repeat
  809. b:=byte(v) and 127;
  810. v:=SarInt64(v,7);
  811. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  812. Done:=true
  813. else
  814. b:=b or 128;
  815. d.write(b,1);
  816. until Done;
  817. end;
  818. procedure TWasmObjOutput.WriteByte(d: tdynamicarray; b: byte);
  819. begin
  820. d.write(b,1);
  821. end;
  822. procedure TWasmObjOutput.WriteName(d: tdynamicarray; const s: string);
  823. begin
  824. WriteUleb(d,Length(s));
  825. d.writestr(s);
  826. end;
  827. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  828. var
  829. b: byte;
  830. begin
  831. b:=ord(wsid);
  832. Writer.write(b,1);
  833. WriteUleb(Writer,FWasmSections[wsid].size);
  834. Writer.writearray(FWasmSections[wsid]);
  835. end;
  836. procedure TWasmObjOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  837. var
  838. b: byte;
  839. begin
  840. b:=0;
  841. Writer.write(b,1);
  842. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  843. Writer.writearray(FWasmCustomSections[wcst]);
  844. end;
  845. procedure TWasmObjOutput.CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  846. var
  847. buf: array [0..4095] of byte;
  848. bs: Integer;
  849. begin
  850. while size>0 do
  851. begin
  852. if size<SizeOf(buf) then
  853. bs:=Integer(size)
  854. else
  855. bs:=SizeOf(buf);
  856. src.read(buf,bs);
  857. dest.write(buf,bs);
  858. dec(size,bs);
  859. end;
  860. end;
  861. procedure TWasmObjOutput.WriteZeros(dest: tdynamicarray; size: QWord);
  862. var
  863. buf : array[0..1023] of byte;
  864. bs: Integer;
  865. begin
  866. fillchar(buf,sizeof(buf),0);
  867. while size>0 do
  868. begin
  869. if size<SizeOf(buf) then
  870. bs:=Integer(size)
  871. else
  872. bs:=SizeOf(buf);
  873. dest.write(buf,bs);
  874. dec(size,bs);
  875. end;
  876. end;
  877. procedure TWasmObjOutput.WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  878. var
  879. i: Integer;
  880. begin
  881. WriteUleb(dest,Length(wrt));
  882. for i:=low(wrt) to high(wrt) do
  883. WriteWasmBasicType(dest,wrt[i]);
  884. end;
  885. procedure TWasmObjOutput.WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  886. begin
  887. WriteByte(dest,encode_wasm_basic_type(wbt));
  888. end;
  889. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  890. var
  891. ExtraData: TWasmObjSymbolExtraData;
  892. begin
  893. if sym.bind=AB_EXTERNAL then
  894. begin
  895. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  896. result:=(ExtraData<>nil) and (ExtraData.TypeIdx<>-1);
  897. end
  898. else
  899. result:=false;
  900. end;
  901. function TWasmObjOutput.IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  902. var
  903. ExtraData: TWasmObjSymbolExtraData;
  904. begin
  905. if (sym.typ=AT_FUNCTION) and not sym.IsAlias then
  906. begin
  907. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  908. result:=(ExtraData<>nil) and (ExtraData.ExportName<>'');
  909. end
  910. else
  911. result:=false;
  912. end;
  913. procedure TWasmObjOutput.WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
  914. var
  915. i,
  916. rle_entries,
  917. cnt: Integer;
  918. lasttype: TWasmBasicType;
  919. begin
  920. if Length(ed.Locals)=0 then
  921. begin
  922. WriteUleb(dest,0);
  923. exit;
  924. end;
  925. rle_entries:=1;
  926. for i:=low(ed.Locals)+1 to high(ed.Locals) do
  927. if ed.Locals[i]<>ed.Locals[i-1] then
  928. inc(rle_entries);
  929. WriteUleb(dest,rle_entries);
  930. lasttype:=ed.Locals[Low(ed.Locals)];
  931. cnt:=1;
  932. for i:=low(ed.Locals)+1 to high(ed.Locals) do
  933. if ed.Locals[i]=ed.Locals[i-1] then
  934. inc(cnt)
  935. else
  936. begin
  937. WriteUleb(dest,cnt);
  938. WriteWasmBasicType(dest,lasttype);
  939. lasttype:=ed.Locals[i];
  940. cnt:=1;
  941. end;
  942. WriteUleb(dest,cnt);
  943. WriteWasmBasicType(dest,lasttype);
  944. end;
  945. procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  946. var
  947. encoded_locals: tdynamicarray;
  948. ObjSymExtraData: TWasmObjSymbolExtraData;
  949. codelen: LongWord;
  950. ObjSection: TWasmObjSection;
  951. codeexprlen: QWord;
  952. begin
  953. ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  954. ObjSection:=TWasmObjSection(objsym.objsection);
  955. ObjSection.Data.seek(objsym.address);
  956. codeexprlen:=objsym.size;
  957. encoded_locals:=tdynamicarray.Create(64);
  958. WriteFunctionLocals(encoded_locals,ObjSymExtraData);
  959. codelen:=encoded_locals.size+codeexprlen+1;
  960. WriteUleb(dest,codelen);
  961. encoded_locals.seek(0);
  962. CopyDynamicArray(encoded_locals,dest,encoded_locals.size);
  963. ObjSection.FileSectionOfs:=dest.size-objsym.offset;
  964. CopyDynamicArray(ObjSection.Data,dest,codeexprlen);
  965. WriteByte(dest,$0B);
  966. encoded_locals.Free;
  967. end;
  968. procedure TWasmObjOutput.WriteSymbolTable;
  969. begin
  970. WriteUleb(FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTableEntriesCount);
  971. FWasmSymbolTable.seek(0);
  972. CopyDynamicArray(FWasmSymbolTable,FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTable.size);
  973. end;
  974. procedure TWasmObjOutput.WriteRelocationCodeTable(CodeSectionIndex: Integer);
  975. begin
  976. WriteUleb(FWasmCustomSections[wcstRelocCode],CodeSectionIndex);
  977. WriteUleb(FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTableEntriesCount);
  978. FWasmRelocationCodeTable.seek(0);
  979. CopyDynamicArray(FWasmRelocationCodeTable,FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTable.size);
  980. end;
  981. procedure TWasmObjOutput.WriteRelocationDataTable(DataSectionIndex: Integer);
  982. begin
  983. WriteUleb(FWasmCustomSections[wcstRelocData],DataSectionIndex);
  984. WriteUleb(FWasmCustomSections[wcstRelocData],FWasmRelocationDataTableEntriesCount);
  985. FWasmRelocationDataTable.seek(0);
  986. CopyDynamicArray(FWasmRelocationDataTable,FWasmCustomSections[wcstRelocData],FWasmRelocationDataTable.size);
  987. end;
  988. procedure TWasmObjOutput.MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  989. begin
  990. if EntriesCount>0 then
  991. begin
  992. WriteUleb(FWasmCustomSections[cst],SectionIndex);
  993. WriteUleb(FWasmCustomSections[cst],EntriesCount);
  994. Table.seek(0);
  995. CopyDynamicArray(Table,FWasmCustomSections[cst],Table.size);
  996. WriteWasmCustomSection(cst);
  997. end;
  998. end;
  999. procedure TWasmObjOutput.WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  1000. begin
  1001. if FWasmLinkingSubsections[wlst].size>0 then
  1002. begin
  1003. WriteByte(FWasmCustomSections[wcstLinking],Ord(wlst));
  1004. WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1005. FWasmLinkingSubsections[wlst].seek(0);
  1006. CopyDynamicArray(FWasmLinkingSubsections[wlst],FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1007. end;
  1008. end;
  1009. procedure TWasmObjOutput.DoRelocations;
  1010. var
  1011. si, ri: Integer;
  1012. objsec: TWasmObjSection;
  1013. objrel: TWasmObjRelocation;
  1014. begin
  1015. for si:=0 to FData.ObjSectionList.Count-1 do
  1016. begin
  1017. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1018. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1019. begin
  1020. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1021. case objrel.typ of
  1022. RELOC_FUNCTION_INDEX_LEB:
  1023. begin
  1024. if not assigned(objrel.symbol) then
  1025. internalerror(2021092509);
  1026. objsec.Data.seek(objrel.DataOffset);
  1027. if TWasmObjSymbol(objrel.symbol).FuncIndex<0 then
  1028. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1029. else
  1030. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
  1031. end;
  1032. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1033. begin
  1034. if not assigned(objrel.symbol) then
  1035. internalerror(2021092605);
  1036. if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1037. begin
  1038. objsec.Data.seek(objrel.DataOffset);
  1039. AddSleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1040. end;
  1041. end;
  1042. RELOC_MEMORY_ADDR_LEB:
  1043. begin
  1044. if not assigned(objrel.symbol) then
  1045. internalerror(2021092606);
  1046. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1047. internalerror(2021092628);
  1048. if objrel.symbol.bind<>AB_EXTERNAL then
  1049. begin
  1050. objsec.Data.seek(objrel.DataOffset);
  1051. AddUleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1052. end;
  1053. end;
  1054. RELOC_ABSOLUTE:
  1055. begin
  1056. if assigned(objrel.ObjSection) then
  1057. begin
  1058. { todo: should we do something here? }
  1059. //Writeln('todo: section relocation');
  1060. end
  1061. else if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1062. begin
  1063. objsec.Data.seek(objrel.DataOffset);
  1064. AddInt32(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1065. end;
  1066. end;
  1067. RELOC_TYPE_INDEX_LEB:
  1068. ;
  1069. RELOC_GLOBAL_INDEX_LEB:
  1070. begin
  1071. if not assigned(objrel.symbol) then
  1072. internalerror(2021092509);
  1073. objsec.Data.seek(objrel.DataOffset);
  1074. if TWasmObjSymbol(objrel.symbol).GlobalIndex<0 then
  1075. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1076. else
  1077. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
  1078. end;
  1079. RELOC_TAG_INDEX_LEB:
  1080. begin
  1081. if not assigned(objrel.symbol) then
  1082. internalerror(2021092716);
  1083. objsec.Data.seek(objrel.DataOffset);
  1084. if TWasmObjSymbol(objrel.symbol).TagIndex<0 then
  1085. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1086. else
  1087. WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
  1088. end;
  1089. else
  1090. internalerror(2021092510);
  1091. end;
  1092. end;
  1093. end;
  1094. end;
  1095. procedure TWasmObjOutput.WriteRelocations;
  1096. var
  1097. si, ri: Integer;
  1098. objsec: TWasmObjSection;
  1099. objrel: TWasmObjRelocation;
  1100. relout: tdynamicarray;
  1101. relcount: PInteger;
  1102. FuncSym: TWasmObjSymbol;
  1103. begin
  1104. for si:=0 to FData.ObjSectionList.Count-1 do
  1105. begin
  1106. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1107. if objsec.IsCode then
  1108. begin
  1109. relout:=FWasmRelocationCodeTable;
  1110. relcount:=@FWasmRelocationCodeTableEntriesCount;
  1111. end
  1112. else if objsec.IsData then
  1113. begin
  1114. relout:=FWasmRelocationDataTable;
  1115. relcount:=@FWasmRelocationDataTableEntriesCount;
  1116. end
  1117. else if objsec.IsDebug then
  1118. begin
  1119. case objsec.Name of
  1120. '.debug_frame':
  1121. begin
  1122. relout:=FWasmRelocationDebugFrameTable;
  1123. relcount:=@FWasmRelocationDebugFrameTableEntriesCount;
  1124. end;
  1125. '.debug_info':
  1126. begin
  1127. relout:=FWasmRelocationDebugInfoTable;
  1128. relcount:=@FWasmRelocationDebugInfoTableEntriesCount;
  1129. end;
  1130. '.debug_line':
  1131. begin
  1132. relout:=FWasmRelocationDebugLineTable;
  1133. relcount:=@FWasmRelocationDebugLineTableEntriesCount;
  1134. end;
  1135. '.debug_abbrev':
  1136. begin
  1137. relout:=FWasmRelocationDebugAbbrevTable;
  1138. relcount:=@FWasmRelocationDebugAbbrevTableEntriesCount;
  1139. end;
  1140. '.debug_aranges':
  1141. begin
  1142. relout:=FWasmRelocationDebugArangesTable;
  1143. relcount:=@FWasmRelocationDebugArangesTableEntriesCount;
  1144. end;
  1145. '.debug_ranges':
  1146. begin
  1147. relout:=FWasmRelocationDebugRangesTable;
  1148. relcount:=@FWasmRelocationDebugRangesTableEntriesCount;
  1149. end;
  1150. '.debug_str':
  1151. begin
  1152. relout:=FWasmRelocationDebugStrTable;
  1153. relcount:=@FWasmRelocationDebugStrTableEntriesCount;
  1154. end;
  1155. else
  1156. internalerror(2022071601);
  1157. end;
  1158. end
  1159. else
  1160. continue;
  1161. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1162. begin
  1163. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1164. case objrel.typ of
  1165. RELOC_FUNCTION_INDEX_LEB:
  1166. begin
  1167. if not assigned(objrel.symbol) then
  1168. internalerror(2021092508);
  1169. Inc(relcount^);
  1170. WriteByte(relout,Ord(R_WASM_FUNCTION_INDEX_LEB));
  1171. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1172. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1173. end;
  1174. RELOC_MEMORY_ADDR_LEB:
  1175. begin
  1176. if not assigned(objrel.symbol) then
  1177. internalerror(2021092603);
  1178. Inc(relcount^);
  1179. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1180. internalerror(2021092628);
  1181. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_LEB));
  1182. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1183. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1184. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1185. end;
  1186. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1187. begin
  1188. if not assigned(objrel.symbol) then
  1189. internalerror(2021092604);
  1190. Inc(relcount^);
  1191. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1192. begin
  1193. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_SLEB));
  1194. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1195. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1196. end
  1197. else
  1198. begin
  1199. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_SLEB));
  1200. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1201. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1202. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1203. end;
  1204. end;
  1205. RELOC_ABSOLUTE:
  1206. begin
  1207. // todo: figure this out, why do these exist?
  1208. //if assigned(objrel.symbol) and not assigned(objrel.symbol.objsection) then
  1209. // Writeln('!!! ', objrel.symbol.name);
  1210. if assigned(objrel.objsection) then
  1211. begin
  1212. Inc(relcount^);
  1213. WriteByte(relout,Ord(R_WASM_SECTION_OFFSET_I32));
  1214. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1215. if (TWasmObjSection(objrel.objsection).SegSymIdx<0) then
  1216. message1(asmw_e_illegal_unset_index,objrel.objsection.name)
  1217. else
  1218. WriteUleb(relout,TWasmObjSection(objrel.objsection).SegSymIdx);
  1219. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1220. end
  1221. else if (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION)) and not objsec.IsDebug then
  1222. begin
  1223. Inc(relcount^);
  1224. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_I32));
  1225. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1226. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1227. end
  1228. else if assigned(objrel.symbol) and assigned(objrel.symbol.objsection) and TWasmObjSection(objrel.symbol.objsection).IsCode then
  1229. begin
  1230. Inc(relcount^);
  1231. WriteByte(relout,Ord(R_WASM_FUNCTION_OFFSET_I32));
  1232. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1233. FuncSym:=FindFunctionSymbol(TWasmObjSymbol(objrel.Symbol));
  1234. if FuncSym.SymbolIndex<0 then
  1235. message1(asmw_e_illegal_unset_index,FuncSym.Name)
  1236. else
  1237. WriteUleb(relout,FuncSym.SymbolIndex);
  1238. WriteSleb(relout,objrel.Addend+objrel.symbol.address); { addend to add to the address }
  1239. end
  1240. else
  1241. begin
  1242. Inc(relcount^);
  1243. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_I32));
  1244. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1245. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1246. begin
  1247. Writeln(objrel.symbol.objsection.Name, ' ', objrel.symbol.name, ' ', objsec.Name);
  1248. message1(asmw_e_illegal_unset_index,objrel.symbol.name);
  1249. end
  1250. else
  1251. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1252. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1253. end;
  1254. end;
  1255. RELOC_TYPE_INDEX_LEB:
  1256. begin
  1257. Inc(relcount^);
  1258. WriteByte(relout,Ord(R_WASM_TYPE_INDEX_LEB));
  1259. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1260. WriteUleb(relout,objrel.TypeIndex);
  1261. end;
  1262. RELOC_GLOBAL_INDEX_LEB:
  1263. begin
  1264. if not assigned(objrel.symbol) then
  1265. internalerror(2021092704);
  1266. Inc(relcount^);
  1267. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_LEB));
  1268. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1269. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1270. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1271. else
  1272. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1273. end;
  1274. RELOC_TAG_INDEX_LEB:
  1275. begin
  1276. if not assigned(objrel.symbol) then
  1277. internalerror(2021092717);
  1278. Inc(relcount^);
  1279. WriteByte(relout,Ord(R_WASM_TAG_INDEX_LEB));
  1280. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1281. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1282. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1283. else
  1284. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1285. end;
  1286. else
  1287. internalerror(2021092507);
  1288. end;
  1289. end;
  1290. end;
  1291. end;
  1292. function TWasmObjOutput.FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  1293. begin
  1294. Result:=TWasmObjSection(Symbol.objsection).MainFuncSymbol;
  1295. end;
  1296. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  1297. var
  1298. section_nr: Integer;
  1299. procedure MaybeAddDebugSectionToSymbolTable(st: TWasmCustomDebugSectionType; var debug_section_nr: Integer);
  1300. var
  1301. objsec: TWasmObjSection;
  1302. begin
  1303. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1304. if Assigned(objsec) then
  1305. begin
  1306. debug_section_nr:=section_nr;
  1307. Inc(section_nr);
  1308. objsec.SegSymIdx:=FWasmSymbolTableEntriesCount;
  1309. Inc(FWasmSymbolTableEntriesCount);
  1310. WriteByte(FWasmSymbolTable,Ord(SYMTAB_SECTION));
  1311. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL);
  1312. WriteUleb(FWasmSymbolTable,debug_section_nr);
  1313. end;
  1314. end;
  1315. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  1316. var
  1317. objsec: TWasmObjSection;
  1318. begin
  1319. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1320. if Assigned(objsec) then
  1321. begin
  1322. if oso_Data in objsec.SecOptions then
  1323. begin
  1324. objsec.Data.seek(0);
  1325. CopyDynamicArray(objsec.Data,FWasmCustomSections[st],objsec.Size);
  1326. end
  1327. else
  1328. WriteZeros(FWasmCustomSections[st],objsec.Size);
  1329. WriteWasmCustomSection(st);
  1330. end;
  1331. end;
  1332. var
  1333. i: Integer;
  1334. objsec: TWasmObjSection;
  1335. segment_count: Integer = 0;
  1336. cur_seg_ofs: qword = 0;
  1337. types_count,
  1338. imports_count, NextImportFunctionIndex, NextFunctionIndex,
  1339. code_section_nr, data_section_nr,
  1340. debug_abbrev_section_nr,debug_info_section_nr,debug_str_section_nr,
  1341. debug_line_section_nr,debug_frame_section_nr,debug_aranges_section_nr,
  1342. debug_ranges_section_nr,
  1343. NextGlobalIndex, NextTagIndex: Integer;
  1344. import_globals_count: Integer = 0;
  1345. globals_count: Integer = 0;
  1346. import_functions_count: Integer = 0;
  1347. export_functions_count: Integer = 0;
  1348. functions_count: Integer = 0;
  1349. import_exception_tags_count: Integer = 0;
  1350. exception_tags_count: Integer = 0;
  1351. objsym, ObjSymAlias: TWasmObjSymbol;
  1352. cust_sec: TWasmCustomSectionType;
  1353. SegmentFlags, SymbolFlags: UInt64;
  1354. begin
  1355. FData:=TWasmObjData(Data);
  1356. { each custom sections starts with its name }
  1357. for cust_sec in TWasmCustomSectionType do
  1358. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  1359. WriteUleb(FWasmCustomSections[wcstLinking],2); { linking metadata version }
  1360. for i:=0 to Data.ObjSymbolList.Count-1 do
  1361. begin
  1362. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1363. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1364. if objsym.bind=AB_EXTERNAL then
  1365. Inc(import_exception_tags_count)
  1366. else
  1367. Inc(exception_tags_count);
  1368. if objsym.typ=AT_WASM_GLOBAL then
  1369. if objsym.bind=AB_EXTERNAL then
  1370. Inc(import_globals_count)
  1371. else
  1372. Inc(globals_count);
  1373. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1374. Inc(import_globals_count);
  1375. if IsExternalFunction(objsym) then
  1376. Inc(import_functions_count);
  1377. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1378. begin
  1379. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  1380. Inc(functions_count);
  1381. end;
  1382. if IsExportedFunction(objsym) then
  1383. Inc(export_functions_count);
  1384. end;
  1385. types_count:=Length(FData.FFuncTypes);
  1386. WriteUleb(FWasmSections[wsiType],types_count);
  1387. for i:=0 to types_count-1 do
  1388. with FData.FFuncTypes[i] do
  1389. begin
  1390. WriteByte(FWasmSections[wsiType],$60);
  1391. WriteWasmResultType(FWasmSections[wsiType],params);
  1392. WriteWasmResultType(FWasmSections[wsiType],results);
  1393. end;
  1394. for i:=0 to Data.ObjSectionList.Count-1 do
  1395. begin
  1396. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1397. if objsec.IsCode then
  1398. objsec.SegIdx:=-1
  1399. else if objsec.IsData then
  1400. begin
  1401. objsec.SegIdx:=segment_count;
  1402. objsec.SegOfs:=cur_seg_ofs;
  1403. Inc(segment_count);
  1404. Inc(cur_seg_ofs,objsec.Size);
  1405. end;
  1406. end;
  1407. imports_count:=2+import_globals_count+import_functions_count+import_exception_tags_count;
  1408. WriteUleb(FWasmSections[wsiImport],imports_count);
  1409. { import memories }
  1410. WriteName(FWasmSections[wsiImport],'env');
  1411. WriteName(FWasmSections[wsiImport],'__linear_memory');
  1412. WriteByte(FWasmSections[wsiImport],$02); { mem }
  1413. WriteByte(FWasmSections[wsiImport],$00); { min }
  1414. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  1415. { import globals }
  1416. NextGlobalIndex:=0;
  1417. for i:=0 to Data.ObjSymbolList.Count-1 do
  1418. begin
  1419. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1420. if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then
  1421. begin
  1422. objsym.GlobalIndex:=NextGlobalIndex;
  1423. Inc(NextGlobalIndex);
  1424. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1425. if objsym.ExtraData.ImportModule<>'' then
  1426. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1427. else
  1428. WriteName(FWasmSections[wsiImport],'env');
  1429. WriteName(FWasmSections[wsiImport],objsym.Name);
  1430. WriteByte(FWasmSections[wsiImport],$03); { global }
  1431. WriteWasmBasicType(FWasmSections[wsiImport],objsym.ExtraData.GlobalType);
  1432. if objsym.ExtraData.GlobalIsImmutable then
  1433. WriteByte(FWasmSections[wsiImport],$00) { const }
  1434. else
  1435. WriteByte(FWasmSections[wsiImport],$01); { var }
  1436. end
  1437. else if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1438. begin
  1439. objsym.GlobalIndex:=NextGlobalIndex;
  1440. Inc(NextGlobalIndex);
  1441. objsym.ExtraData:=nil;
  1442. WriteName(FWasmSections[wsiImport],'GOT.mem');
  1443. WriteName(FWasmSections[wsiImport],objsym.Name);
  1444. WriteByte(FWasmSections[wsiImport],$03); { global }
  1445. WriteWasmBasicType(FWasmSections[wsiImport],wbt_i32); { i32 }
  1446. WriteByte(FWasmSections[wsiImport],$01); { var }
  1447. end;
  1448. end;
  1449. { import functions }
  1450. NextImportFunctionIndex:=0;
  1451. for i:=0 to Data.ObjSymbolList.Count-1 do
  1452. begin
  1453. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1454. if IsExternalFunction(objsym) then
  1455. begin
  1456. objsym.FuncIndex:=NextImportFunctionIndex;
  1457. Inc(NextImportFunctionIndex);
  1458. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1459. if objsym.ExtraData.ImportModule<>'' then
  1460. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1461. else
  1462. WriteName(FWasmSections[wsiImport],'env');
  1463. WriteName(FWasmSections[wsiImport],objsym.Name);
  1464. WriteByte(FWasmSections[wsiImport],$00); { func }
  1465. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1466. end;
  1467. end;
  1468. { import tables }
  1469. WriteName(FWasmSections[wsiImport],'env');
  1470. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  1471. WriteByte(FWasmSections[wsiImport],$01); { table }
  1472. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  1473. WriteByte(FWasmSections[wsiImport],$00); { min }
  1474. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  1475. { import tags }
  1476. NextTagIndex:=0;
  1477. for i:=0 to Data.ObjSymbolList.Count-1 do
  1478. begin
  1479. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1480. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind=AB_EXTERNAL) then
  1481. begin
  1482. objsym.TagIndex:=NextTagIndex;
  1483. Inc(NextTagIndex);
  1484. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1485. if objsym.ExtraData.ImportModule<>'' then
  1486. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1487. else
  1488. WriteName(FWasmSections[wsiImport],'env');
  1489. WriteName(FWasmSections[wsiImport],objsym.Name);
  1490. WriteByte(FWasmSections[wsiImport],$04); { tag }
  1491. WriteByte(FWasmSections[wsiImport],$00); { exception }
  1492. WriteUleb(FWasmSections[wsiImport],objsym.ExtraData.ExceptionTagTypeIdx);
  1493. end;
  1494. end;
  1495. WriteUleb(FWasmSections[wsiFunction],functions_count);
  1496. NextFunctionIndex:=NextImportFunctionIndex;
  1497. for i:=0 to Data.ObjSymbolList.Count-1 do
  1498. begin
  1499. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1500. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1501. begin
  1502. objsym.FuncIndex:=NextFunctionIndex;
  1503. Inc(NextFunctionIndex);
  1504. WriteUleb(FWasmSections[wsiFunction],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1505. end;
  1506. end;
  1507. if exception_tags_count>0 then
  1508. begin
  1509. WriteUleb(FWasmSections[wsiTag],exception_tags_count);
  1510. for i:=0 to Data.ObjSymbolList.Count-1 do
  1511. begin
  1512. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1513. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind<>AB_EXTERNAL) then
  1514. begin
  1515. objsym.TagIndex:=NextTagIndex;
  1516. Inc(NextTagIndex);
  1517. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1518. WriteByte(FWasmSections[wsiTag],$00); { exception }
  1519. WriteUleb(FWasmSections[wsiTag],objsym.ExtraData.ExceptionTagTypeIdx);
  1520. end;
  1521. end;
  1522. end;
  1523. if globals_count>0 then
  1524. begin
  1525. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  1526. for i:=0 to Data.ObjSymbolList.Count-1 do
  1527. begin
  1528. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1529. if (objsym.typ=AT_WASM_GLOBAL) and (objsym.bind<>AB_EXTERNAL) then
  1530. begin
  1531. objsym.GlobalIndex:=NextGlobalIndex;
  1532. Inc(NextGlobalIndex);
  1533. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1534. WriteWasmBasicType(FWasmSections[wsiGlobal],objsym.ExtraData.GlobalType);
  1535. if objsym.ExtraData.GlobalIsImmutable then
  1536. WriteByte(FWasmSections[wsiGlobal],$00) { const }
  1537. else
  1538. WriteByte(FWasmSections[wsiGlobal],$01); { var }
  1539. { init expr }
  1540. case objsym.ExtraData.GlobalType of
  1541. wbt_i32:
  1542. begin
  1543. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  1544. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1545. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1546. end;
  1547. wbt_i64:
  1548. begin
  1549. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  1550. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1551. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1552. end;
  1553. wbt_f32:
  1554. begin
  1555. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  1556. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE single precision floating point format) }
  1557. WriteByte(FWasmSections[wsiGlobal],$00);
  1558. WriteByte(FWasmSections[wsiGlobal],$00);
  1559. WriteByte(FWasmSections[wsiGlobal],$00);
  1560. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1561. end;
  1562. wbt_f64:
  1563. begin
  1564. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  1565. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE double precision floating point format) }
  1566. WriteByte(FWasmSections[wsiGlobal],$00);
  1567. WriteByte(FWasmSections[wsiGlobal],$00);
  1568. WriteByte(FWasmSections[wsiGlobal],$00);
  1569. WriteByte(FWasmSections[wsiGlobal],$00);
  1570. WriteByte(FWasmSections[wsiGlobal],$00);
  1571. WriteByte(FWasmSections[wsiGlobal],$00);
  1572. WriteByte(FWasmSections[wsiGlobal],$00);
  1573. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1574. end;
  1575. wbt_externref:
  1576. begin
  1577. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null extern }
  1578. WriteByte(FWasmSections[wsiGlobal],$6F);
  1579. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1580. end;
  1581. wbt_funcref:
  1582. begin
  1583. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null func }
  1584. WriteByte(FWasmSections[wsiGlobal],$70);
  1585. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1586. end;
  1587. else
  1588. internalerror(2022052801);
  1589. end;
  1590. end;
  1591. end;
  1592. end;
  1593. if export_functions_count>0 then
  1594. begin
  1595. WriteUleb(FWasmSections[wsiExport],export_functions_count);
  1596. for i:=0 to Data.ObjSymbolList.Count-1 do
  1597. begin
  1598. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1599. if IsExportedFunction(objsym) then
  1600. begin
  1601. WriteName(FWasmSections[wsiExport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).ExportName);
  1602. WriteByte(FWasmSections[wsiExport],0); { func }
  1603. if (objsym.FuncIndex<0) then
  1604. message1(asmw_e_illegal_unset_index,objsym.name)
  1605. else
  1606. WriteUleb(FWasmSections[wsiExport],objsym.FuncIndex);
  1607. end;
  1608. end;
  1609. end;
  1610. for i:=0 to Data.ObjSymbolList.Count-1 do
  1611. begin
  1612. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1613. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1614. begin
  1615. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1616. Inc(FWasmSymbolTableEntriesCount);
  1617. WriteByte(FWasmSymbolTable,Ord(SYMTAB_EVENT));
  1618. if objsym.bind=AB_GLOBAL then
  1619. WriteUleb(FWasmSymbolTable,0)
  1620. else if objsym.bind=AB_LOCAL then
  1621. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
  1622. else if objsym.bind=AB_EXTERNAL then
  1623. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
  1624. else if objsym.bind=AB_WEAK then
  1625. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_WEAK)
  1626. else
  1627. internalerror(2021092715);
  1628. if (objsym.TagIndex<0) then
  1629. message1(asmw_e_illegal_unset_index,objsym.name)
  1630. else
  1631. WriteUleb(FWasmSymbolTable,objsym.TagIndex);
  1632. if objsym.bind<>AB_EXTERNAL then
  1633. WriteName(FWasmSymbolTable,objsym.Name);
  1634. end
  1635. else if objsym.typ=AT_WASM_GLOBAL then
  1636. begin
  1637. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1638. Inc(FWasmSymbolTableEntriesCount);
  1639. WriteByte(FWasmSymbolTable,Ord(SYMTAB_GLOBAL));
  1640. if objsym.bind=AB_EXTERNAL then
  1641. begin
  1642. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  1643. if (objsym.GlobalIndex<0) then
  1644. message1(asmw_e_illegal_unset_index,objsym.name)
  1645. else
  1646. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  1647. end
  1648. else
  1649. begin
  1650. WriteUleb(FWasmSymbolTable,0);
  1651. if (objsym.GlobalIndex<0) then
  1652. message1(asmw_e_illegal_unset_index,objsym.name)
  1653. else
  1654. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  1655. WriteName(FWasmSymbolTable,objsym.Name);
  1656. end;
  1657. end
  1658. else if IsExternalFunction(objsym) then
  1659. begin
  1660. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1661. Inc(FWasmSymbolTableEntriesCount);
  1662. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  1663. if objsym.ExtraData.ImportModule<>'' then
  1664. begin
  1665. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED or WASM_SYM_EXPLICIT_NAME);
  1666. if (objsym.FuncIndex<0) then
  1667. message1(asmw_e_illegal_unset_index,objsym.name)
  1668. else
  1669. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  1670. WriteName(FWasmSymbolTable,objsym.Name);
  1671. end
  1672. else
  1673. begin
  1674. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  1675. if (objsym.FuncIndex<0) then
  1676. message1(asmw_e_illegal_unset_index,objsym.name)
  1677. else
  1678. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  1679. end;
  1680. end
  1681. else if objsym.typ=AT_FUNCTION then
  1682. begin
  1683. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1684. Inc(FWasmSymbolTableEntriesCount);
  1685. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  1686. if objsym.IsAlias then
  1687. begin
  1688. ObjSymAlias:=TWasmObjSymbol(Data.ObjSymbolList.Find(objsym.AliasOf));
  1689. ObjSym.FuncIndex:=ObjSymAlias.FuncIndex;
  1690. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPLICIT_NAME or WASM_SYM_NO_STRIP);
  1691. WriteUleb(FWasmSymbolTable,ObjSymAlias.FuncIndex);
  1692. end
  1693. else
  1694. begin
  1695. if IsExportedFunction(objsym) then
  1696. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPORTED)
  1697. else
  1698. WriteUleb(FWasmSymbolTable,0);
  1699. if (objsym.FuncIndex<0) then
  1700. message1(asmw_e_illegal_unset_index,objsym.name)
  1701. else
  1702. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  1703. end;
  1704. WriteName(FWasmSymbolTable,objsym.Name);
  1705. end
  1706. else if (objsym.typ in [AT_DATA,AT_TLS]) or ((objsym.typ=AT_NONE) and (objsym.bind=AB_EXTERNAL)) then
  1707. begin
  1708. if (objsym.bind<>AB_EXTERNAL) and TWasmObjSection(objsym.objsection).IsDebug then
  1709. begin
  1710. {todo: debug symbols}
  1711. end
  1712. else
  1713. begin
  1714. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  1715. Inc(FWasmSymbolTableEntriesCount);
  1716. WriteByte(FWasmSymbolTable,Ord(SYMTAB_DATA));
  1717. if objsym.bind=AB_GLOBAL then
  1718. SymbolFlags:=0
  1719. else if objsym.bind=AB_LOCAL then
  1720. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  1721. else if objsym.bind=AB_EXTERNAL then
  1722. SymbolFlags:=WASM_SYM_UNDEFINED
  1723. else
  1724. internalerror(2021092506);
  1725. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1726. SymbolFlags:=(SymbolFlags and not WASM_SYM_BINDING_LOCAL) or WASM_SYM_TLS;
  1727. WriteUleb(FWasmSymbolTable,SymbolFlags);
  1728. WriteName(FWasmSymbolTable,objsym.Name);
  1729. if objsym.bind<>AB_EXTERNAL then
  1730. begin
  1731. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).SegIdx);
  1732. WriteUleb(FWasmSymbolTable,objsym.offset);
  1733. WriteUleb(FWasmSymbolTable,objsym.size);
  1734. end;
  1735. end;
  1736. end;
  1737. end;
  1738. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  1739. Writer.write(WasmVersion,SizeOf(WasmVersion));
  1740. if ts_wasm_threads in current_settings.targetswitches then
  1741. begin
  1742. WriteUleb(FWasmCustomSections[wcstTargetFeatures],4);
  1743. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1744. WriteName(FWasmCustomSections[wcstTargetFeatures],'atomics');
  1745. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1746. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1747. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1748. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1749. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1750. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1751. end
  1752. else
  1753. begin
  1754. WriteUleb(FWasmCustomSections[wcstTargetFeatures],3);
  1755. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1756. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1757. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1758. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1759. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1760. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1761. end;
  1762. { Write the producers section:
  1763. https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md }
  1764. WriteUleb(FWasmCustomSections[wcstProducers],2);
  1765. WriteName(FWasmCustomSections[wcstProducers],'language');
  1766. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1767. WriteName(FWasmCustomSections[wcstProducers],'Pascal');
  1768. WriteName(FWasmCustomSections[wcstProducers],'');
  1769. WriteName(FWasmCustomSections[wcstProducers],'processed-by');
  1770. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1771. WriteName(FWasmCustomSections[wcstProducers],'Free Pascal Compiler (FPC)');
  1772. WriteName(FWasmCustomSections[wcstProducers],full_version_string+' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname);
  1773. code_section_nr:=-1;
  1774. data_section_nr:=-1;
  1775. debug_abbrev_section_nr:=-1;
  1776. debug_info_section_nr:=-1;
  1777. debug_str_section_nr:=-1;
  1778. debug_line_section_nr:=-1;
  1779. debug_frame_section_nr:=-1;
  1780. debug_aranges_section_nr:=-1;
  1781. debug_ranges_section_nr:=-1;
  1782. section_nr:=0;
  1783. WriteWasmSection(wsiType);
  1784. Inc(section_nr);
  1785. WriteWasmSection(wsiImport);
  1786. Inc(section_nr);
  1787. WriteWasmSection(wsiFunction);
  1788. Inc(section_nr);
  1789. if exception_tags_count>0 then
  1790. begin
  1791. WriteWasmSection(wsiTag);
  1792. Inc(section_nr);
  1793. end;
  1794. if globals_count>0 then
  1795. begin
  1796. WriteWasmSection(wsiGlobal);
  1797. Inc(section_nr);
  1798. end;
  1799. if export_functions_count>0 then
  1800. begin
  1801. WriteWasmSection(wsiExport);
  1802. Inc(section_nr);
  1803. end;
  1804. { determine the section numbers for the datacount, code, data and debug sections ahead of time }
  1805. if segment_count>0 then
  1806. Inc(section_nr); { the DataCount section }
  1807. code_section_nr:=section_nr; { the Code section }
  1808. Inc(section_nr);
  1809. if segment_count>0 then
  1810. begin
  1811. data_section_nr:=section_nr; { the Data section }
  1812. Inc(section_nr);
  1813. end;
  1814. { the debug sections }
  1815. MaybeAddDebugSectionToSymbolTable(wcstDebugAbbrev,debug_abbrev_section_nr);
  1816. MaybeAddDebugSectionToSymbolTable(wcstDebugInfo,debug_info_section_nr);
  1817. MaybeAddDebugSectionToSymbolTable(wcstDebugStr,debug_str_section_nr);
  1818. MaybeAddDebugSectionToSymbolTable(wcstDebugLine,debug_line_section_nr);
  1819. MaybeAddDebugSectionToSymbolTable(wcstDebugFrame,debug_frame_section_nr);
  1820. MaybeAddDebugSectionToSymbolTable(wcstDebugAranges,debug_aranges_section_nr);
  1821. MaybeAddDebugSectionToSymbolTable(wcstDebugRanges,debug_ranges_section_nr);
  1822. DoRelocations;
  1823. if segment_count>0 then
  1824. begin
  1825. WriteUleb(FWasmSections[wsiData],segment_count);
  1826. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  1827. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],segment_count);
  1828. for i:=0 to Data.ObjSectionList.Count-1 do
  1829. begin
  1830. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1831. if objsec.IsData then
  1832. begin
  1833. WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],objsec.Name);
  1834. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(objsec.SecAlign));
  1835. SegmentFlags:=0;
  1836. if (ts_wasm_threads in current_settings.targetswitches) and
  1837. (oso_threadvar in objsec.SecOptions) then
  1838. SegmentFlags:=SegmentFlags or WASM_SEG_FLAG_TLS;
  1839. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],SegmentFlags); { flags }
  1840. WriteByte(FWasmSections[wsiData],0);
  1841. WriteByte(FWasmSections[wsiData],$41);
  1842. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  1843. WriteByte(FWasmSections[wsiData],$0b);
  1844. WriteUleb(FWasmSections[wsiData],objsec.Size);
  1845. objsec.FileSectionOfs:=FWasmSections[wsiData].size;
  1846. if oso_Data in objsec.SecOptions then
  1847. begin
  1848. objsec.Data.seek(0);
  1849. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  1850. end
  1851. else
  1852. begin
  1853. WriteZeros(FWasmSections[wsiData],objsec.Size);
  1854. end;
  1855. end;
  1856. end;
  1857. end;
  1858. WriteUleb(FWasmSections[wsiCode],functions_count);
  1859. for i:=0 to Data.ObjSymbolList.Count-1 do
  1860. begin
  1861. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1862. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1863. WriteFunctionCode(FWasmSections[wsiCode],objsym);
  1864. end;
  1865. if segment_count>0 then
  1866. WriteWasmSection(wsiDataCount);
  1867. WriteWasmSection(wsiCode);
  1868. if segment_count>0 then
  1869. WriteWasmSection(wsiData);
  1870. MaybeWriteDebugSection(wcstDebugAbbrev);
  1871. MaybeWriteDebugSection(wcstDebugInfo);
  1872. MaybeWriteDebugSection(wcstDebugStr);
  1873. MaybeWriteDebugSection(wcstDebugLine);
  1874. MaybeWriteDebugSection(wcstDebugFrame);
  1875. MaybeWriteDebugSection(wcstDebugAranges);
  1876. MaybeWriteDebugSection(wcstDebugRanges);
  1877. WriteRelocations;
  1878. WriteSymbolTable;
  1879. WriteLinkingSubsection(WASM_SYMBOL_TABLE);
  1880. if segment_count>0 then
  1881. WriteLinkingSubsection(WASM_SEGMENT_INFO);
  1882. WriteRelocationCodeTable(code_section_nr);
  1883. if segment_count>0 then
  1884. WriteRelocationDataTable(data_section_nr);
  1885. WriteWasmCustomSection(wcstLinking);
  1886. Inc(section_nr);
  1887. WriteWasmCustomSection(wcstRelocCode);
  1888. Inc(section_nr);
  1889. if segment_count>0 then
  1890. begin
  1891. WriteWasmCustomSection(wcstRelocData);
  1892. Inc(section_nr);
  1893. end;
  1894. MaybeWriteRelocationDebugTable(wcstRelocDebugAbbrev,debug_abbrev_section_nr,FWasmRelocationDebugAbbrevTableEntriesCount,FWasmRelocationDebugAbbrevTable);
  1895. MaybeWriteRelocationDebugTable(wcstRelocDebugInfo,debug_info_section_nr,FWasmRelocationDebugInfoTableEntriesCount,FWasmRelocationDebugInfoTable);
  1896. MaybeWriteRelocationDebugTable(wcstRelocDebugStr,debug_str_section_nr,FWasmRelocationDebugStrTableEntriesCount,FWasmRelocationDebugStrTable);
  1897. MaybeWriteRelocationDebugTable(wcstRelocDebugLine,debug_line_section_nr,FWasmRelocationDebugLineTableEntriesCount,FWasmRelocationDebugLineTable);
  1898. MaybeWriteRelocationDebugTable(wcstRelocDebugFrame,debug_frame_section_nr,FWasmRelocationDebugFrameTableEntriesCount,FWasmRelocationDebugFrameTable);
  1899. MaybeWriteRelocationDebugTable(wcstRelocDebugAranges,debug_aranges_section_nr,FWasmRelocationDebugArangesTableEntriesCount,FWasmRelocationDebugArangesTable);
  1900. MaybeWriteRelocationDebugTable(wcstRelocDebugRanges,debug_ranges_section_nr,FWasmRelocationDebugRangesTableEntriesCount,FWasmRelocationDebugRangesTable);
  1901. WriteWasmCustomSection(wcstProducers);
  1902. Inc(section_nr);
  1903. WriteWasmCustomSection(wcstTargetFeatures);
  1904. Inc(section_nr);
  1905. result:=true;
  1906. end;
  1907. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  1908. var
  1909. i: TWasmSectionID;
  1910. j: TWasmCustomSectionType;
  1911. k: TWasmLinkingSubsectionType;
  1912. begin
  1913. inherited;
  1914. cobjdata:=TWasmObjData;
  1915. for i in TWasmSectionID do
  1916. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  1917. for j in TWasmCustomSectionType do
  1918. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  1919. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  1920. FWasmLinkingSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  1921. FWasmSymbolTable:=tdynamicarray.create(SectionDataMaxGrow);
  1922. FWasmSymbolTableEntriesCount:=0;
  1923. FWasmRelocationCodeTable:=tdynamicarray.create(SectionDataMaxGrow);
  1924. FWasmRelocationCodeTableEntriesCount:=0;
  1925. FWasmRelocationDataTable:=tdynamicarray.create(SectionDataMaxGrow);
  1926. FWasmRelocationDataTableEntriesCount:=0;
  1927. FWasmRelocationDebugFrameTable:=tdynamicarray.create(SectionDataMaxGrow);
  1928. FWasmRelocationDebugFrameTableEntriesCount:=0;
  1929. FWasmRelocationDebugInfoTable:=tdynamicarray.create(SectionDataMaxGrow);
  1930. FWasmRelocationDebugInfoTableEntriesCount:=0;
  1931. FWasmRelocationDebugLineTable:=tdynamicarray.create(SectionDataMaxGrow);
  1932. FWasmRelocationDebugLineTableEntriesCount:=0;
  1933. FWasmRelocationDebugAbbrevTable:=tdynamicarray.create(SectionDataMaxGrow);
  1934. FWasmRelocationDebugAbbrevTableEntriesCount:=0;
  1935. FWasmRelocationDebugArangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  1936. FWasmRelocationDebugArangesTableEntriesCount:=0;
  1937. FWasmRelocationDebugRangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  1938. FWasmRelocationDebugRangesTableEntriesCount:=0;
  1939. FWasmRelocationDebugStrTable:=tdynamicarray.create(SectionDataMaxGrow);
  1940. FWasmRelocationDebugStrTableEntriesCount:=0;
  1941. end;
  1942. destructor TWasmObjOutput.destroy;
  1943. var
  1944. i: TWasmSectionID;
  1945. j: TWasmCustomSectionType;
  1946. k: TWasmLinkingSubsectionType;
  1947. begin
  1948. for i in TWasmSectionID do
  1949. FWasmSections[i].Free;
  1950. for j in TWasmCustomSectionType do
  1951. FWasmCustomSections[j].Free;
  1952. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  1953. FWasmLinkingSubsections[k].Free;
  1954. FWasmSymbolTable.Free;
  1955. FWasmRelocationCodeTable.Free;
  1956. FWasmRelocationDataTable.Free;
  1957. FWasmRelocationDebugFrameTable.Free;
  1958. FWasmRelocationDebugInfoTable.Free;
  1959. FWasmRelocationDebugLineTable.Free;
  1960. FWasmRelocationDebugAbbrevTable.Free;
  1961. FWasmRelocationDebugArangesTable.Free;
  1962. FWasmRelocationDebugRangesTable.Free;
  1963. FWasmRelocationDebugStrTable.Free;
  1964. inherited destroy;
  1965. end;
  1966. {****************************************************************************
  1967. TWasmObjInput
  1968. ****************************************************************************}
  1969. function TWasmObjInput.ReadUleb(r: TObjectReader; out v: uint64): boolean;
  1970. var
  1971. b: byte;
  1972. shift:integer;
  1973. begin
  1974. result:=false;
  1975. b:=0;
  1976. v:=0;
  1977. shift:=0;
  1978. repeat
  1979. if not r.read(b,1) then
  1980. exit;
  1981. v:=v or (uint64(b and 127) shl shift);
  1982. inc(shift,7);
  1983. until (b and 128)=0;
  1984. result:=true;
  1985. end;
  1986. constructor TWasmObjInput.create;
  1987. begin
  1988. inherited create;
  1989. cobjdata:=TWasmObjData;
  1990. end;
  1991. destructor TWasmObjInput.Destroy;
  1992. var
  1993. i: Integer;
  1994. begin
  1995. for i:=low(FFuncTypes) to high(FFuncTypes) do
  1996. begin
  1997. FFuncTypes[i].free;
  1998. FFuncTypes[i]:=nil;
  1999. end;
  2000. inherited Destroy;
  2001. end;
  2002. class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  2003. var
  2004. ModuleMagic: array [0..3] of Byte;
  2005. ModuleVersion: array [0..3] of Byte;
  2006. i: Integer;
  2007. begin
  2008. Writeln('CanReadObjData');
  2009. result:=false;
  2010. if not AReader.read(ModuleMagic,4) then
  2011. exit;
  2012. for i:=0 to 3 do
  2013. if ModuleMagic[i]<>WasmModuleMagic[i] then
  2014. exit;
  2015. if not AReader.read(ModuleVersion,4) then
  2016. exit;
  2017. for i:=0 to 3 do
  2018. if ModuleVersion[i]<>WasmVersion[i] then
  2019. exit;
  2020. result:=true;
  2021. end;
  2022. function TWasmObjInput.ReadObjData(AReader: TObjectreader; out ObjData: TObjData): boolean;
  2023. function ReadSection: Boolean;
  2024. var
  2025. SectionId: Byte;
  2026. SectionSize: uint64;
  2027. SectionStart: LongInt;
  2028. TypeSectionRead: Boolean = false;
  2029. function ReadCustomSection: Boolean;
  2030. begin
  2031. Result:=False;
  2032. end;
  2033. function ReadTypeSection: Boolean;
  2034. var
  2035. FuncTypesCount, ParamsCount, ResultsCount: uint64;
  2036. FuncTypeId, WasmTypeId: Byte;
  2037. i, j: Integer;
  2038. wbt: TWasmBasicType;
  2039. begin
  2040. Result:=False;
  2041. if TypeSectionRead then
  2042. begin
  2043. InputError('Type section is duplicated');
  2044. exit;
  2045. end;
  2046. TypeSectionRead:=True;
  2047. if not ReadUleb(AReader, FuncTypesCount) then
  2048. begin
  2049. InputError('Error reading the func types count');
  2050. exit;
  2051. end;
  2052. if AReader.Pos>(SectionStart+SectionSize) then
  2053. begin
  2054. InputError('The func types count stretches beyond the end of the type section');
  2055. exit;
  2056. end;
  2057. if FuncTypesCount>high(uint32) then
  2058. begin
  2059. InputError('The func types count does not fit in an unsigned 32-bit int');
  2060. exit;
  2061. end;
  2062. SetLength(FFuncTypes,FuncTypesCount);
  2063. for i:=0 to FuncTypesCount - 1 do
  2064. begin
  2065. FFuncTypes[i]:=TWasmFuncType.Create([],[]);
  2066. if not AReader.read(FuncTypeId,1) then
  2067. begin
  2068. InputError('Error reading the function type identifier');
  2069. exit;
  2070. end;
  2071. if FuncTypeId<>$60 then
  2072. begin
  2073. InputError('Incorrect function type identifier (expected $60, got $' + HexStr(FuncTypeId,2) + ')');
  2074. exit;
  2075. end;
  2076. if not ReadUleb(AReader, ParamsCount) then
  2077. begin
  2078. InputError('Error reading the function parameters count');
  2079. exit;
  2080. end;
  2081. if AReader.Pos>(SectionStart+SectionSize) then
  2082. begin
  2083. InputError('The function paramaters count stretches beyond the end of the type section');
  2084. exit;
  2085. end;
  2086. if ParamsCount>high(uint32) then
  2087. begin
  2088. InputError('The function parameters count does not fit in an unsigned 32-bit int');
  2089. exit;
  2090. end;
  2091. for j:=0 to ParamsCount-1 do
  2092. begin
  2093. if not AReader.read(WasmTypeId,1) then
  2094. begin
  2095. InputError('Error reading a function parameter basic type');
  2096. exit;
  2097. end;
  2098. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  2099. begin
  2100. InputError('Unknown function parameter basic type: $' + HexStr(WasmTypeId,2));
  2101. exit;
  2102. end;
  2103. FFuncTypes[i].add_param(wbt);
  2104. end;
  2105. if not ReadUleb(AReader, ResultsCount) then
  2106. begin
  2107. InputError('Error reading the function results count');
  2108. exit;
  2109. end;
  2110. if AReader.Pos>(SectionStart+SectionSize) then
  2111. begin
  2112. InputError('The function results count stretches beyond the end of the type section');
  2113. exit;
  2114. end;
  2115. if ResultsCount>high(uint32) then
  2116. begin
  2117. InputError('The function results count does not fit in an unsigned 32-bit int');
  2118. exit;
  2119. end;
  2120. for j:=0 to ResultsCount-1 do
  2121. begin
  2122. if not AReader.read(WasmTypeId,1) then
  2123. begin
  2124. InputError('Error reading a function result basic type');
  2125. exit;
  2126. end;
  2127. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  2128. begin
  2129. InputError('Unknown function result basic type: $' + HexStr(WasmTypeId,2));
  2130. exit;
  2131. end;
  2132. FFuncTypes[i].add_result(wbt);
  2133. end;
  2134. end;
  2135. if AReader.Pos<>(SectionStart+SectionSize) then
  2136. begin
  2137. InputError('Unexpected type section size');
  2138. exit;
  2139. end;
  2140. Result:=true;
  2141. end;
  2142. function ReadImportSection: Boolean;
  2143. begin
  2144. Result:=False;
  2145. end;
  2146. function ReadFunctionSection: Boolean;
  2147. begin
  2148. Result:=False;
  2149. end;
  2150. function ReadGlobalSection: Boolean;
  2151. begin
  2152. Result:=False;
  2153. end;
  2154. function ReadExportSection: Boolean;
  2155. begin
  2156. Result:=False;
  2157. end;
  2158. function ReadCodeSection: Boolean;
  2159. begin
  2160. Result:=False;
  2161. end;
  2162. function ReadDataSection: Boolean;
  2163. begin
  2164. Result:=False;
  2165. end;
  2166. function ReadDataCountSection: Boolean;
  2167. begin
  2168. Result:=False;
  2169. end;
  2170. begin
  2171. Result:=False;
  2172. if not AReader.read(SectionId,1) then
  2173. begin
  2174. InputError('Error reading section ID');
  2175. exit;
  2176. end;
  2177. if not ReadUleb(AReader,SectionSize) then
  2178. begin
  2179. InputError('Error reading section size');
  2180. exit;
  2181. end;
  2182. if SectionSize>high(uint32) then
  2183. begin
  2184. InputError('Invalid section size');
  2185. exit;
  2186. end;
  2187. if (AReader.Pos+SectionSize)>AReader.size then
  2188. begin
  2189. InputError('Section exceeds beyond the end of file');
  2190. exit;
  2191. end;
  2192. SectionStart:=AReader.Pos;
  2193. { skip the section for now... TODO: parse the section }
  2194. case SectionId of
  2195. Byte(wsiCustom):
  2196. Result := ReadCustomSection;
  2197. Byte(wsiType):
  2198. if not ReadTypeSection then
  2199. begin
  2200. InputError('Error reading the type section');
  2201. exit;
  2202. end;
  2203. Byte(wsiImport):
  2204. Result := ReadImportSection;
  2205. Byte(wsiFunction):
  2206. Result := ReadFunctionSection;
  2207. Byte(wsiGlobal):
  2208. Result := ReadGlobalSection;
  2209. Byte(wsiExport):
  2210. Result := ReadExportSection;
  2211. Byte(wsiCode):
  2212. Result := ReadCodeSection;
  2213. Byte(wsiData):
  2214. Result := ReadDataSection;
  2215. Byte(wsiDataCount):
  2216. Result := ReadDataCountSection;
  2217. else
  2218. begin
  2219. InputError('Unknown section: ' + ToStr(SectionId));
  2220. exit;
  2221. end;
  2222. end;
  2223. if SectionSize>0 then
  2224. AReader.seek(SectionStart+SectionSize);
  2225. Result:=True;
  2226. end;
  2227. var
  2228. ModuleMagic: array [0..3] of Byte;
  2229. ModuleVersion: array [0..3] of Byte;
  2230. i: Integer;
  2231. begin
  2232. objdata:=CObjData.Create(InputFileName);
  2233. result:=false;
  2234. if not AReader.read(ModuleMagic,4) then
  2235. exit;
  2236. for i:=0 to 3 do
  2237. if ModuleMagic[i]<>WasmModuleMagic[i] then
  2238. exit;
  2239. if not AReader.read(ModuleVersion,4) then
  2240. exit;
  2241. for i:=0 to 3 do
  2242. if ModuleVersion[i]<>WasmVersion[i] then
  2243. exit;
  2244. while AReader.Pos<AReader.size do
  2245. if not ReadSection then
  2246. exit;
  2247. Result:=True;
  2248. end;
  2249. {****************************************************************************
  2250. TWasmExeOutput
  2251. ****************************************************************************}
  2252. function TWasmExeOutput.writeData: boolean;
  2253. begin
  2254. result:=false;
  2255. {TODO: implement}
  2256. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  2257. Writer.write(WasmVersion,SizeOf(WasmVersion));
  2258. result := true;
  2259. end;
  2260. procedure TWasmExeOutput.DoRelocationFixup(objsec: TObjSection);
  2261. begin
  2262. {TODO: implement}
  2263. end;
  2264. constructor TWasmExeOutput.create;
  2265. begin
  2266. inherited create;
  2267. CObjData:=TWasmObjData;
  2268. end;
  2269. {****************************************************************************
  2270. TWasmAssembler
  2271. ****************************************************************************}
  2272. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  2273. begin
  2274. inherited;
  2275. CObjOutput:=TWasmObjOutput;
  2276. end;
  2277. {*****************************************************************************
  2278. Initialize
  2279. *****************************************************************************}
  2280. {$ifdef wasm32}
  2281. const
  2282. as_wasm32_wasm_info : tasminfo =
  2283. (
  2284. id : as_wasm32_wasm;
  2285. idtxt : 'WASM';
  2286. asmbin : '';
  2287. asmcmd : '';
  2288. supported_targets : [system_wasm32_embedded,system_wasm32_wasi];
  2289. flags : [af_outputbinary,af_smartlink_sections];
  2290. labelprefix : '..@';
  2291. labelmaxlen : -1;
  2292. comment : '; ';
  2293. dollarsign: '$';
  2294. );
  2295. {$endif wasm32}
  2296. initialization
  2297. {$ifdef wasm32}
  2298. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  2299. {$endif wasm32}
  2300. end.