ogwasm.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. globtype,
  23. { target }
  24. systems,
  25. { assembler }
  26. aasmbase,assemble,
  27. { WebAssembly module format definitions }
  28. wasmbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. { TWasmObjSection }
  34. TWasmObjSection = class(TObjSection)
  35. end;
  36. { TWasmObjData }
  37. TWasmObjData = class(TObjData)
  38. private
  39. function is_smart_section(atype:TAsmSectiontype):boolean;
  40. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  41. public
  42. constructor create(const n:string);override;
  43. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  44. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  45. end;
  46. { TWasmObjOutput }
  47. TWasmObjOutput = class(tObjOutput)
  48. protected
  49. function writeData(Data:TObjData):boolean;override;
  50. public
  51. constructor create(AWriter:TObjectWriter);override;
  52. end;
  53. { TWasmAssembler }
  54. TWasmAssembler = class(tinternalassembler)
  55. constructor create(info: pasminfo; smart:boolean);override;
  56. end;
  57. implementation
  58. {****************************************************************************
  59. TWasmObjData
  60. ****************************************************************************}
  61. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  62. begin
  63. { For bss we need to set some flags that are target dependent,
  64. it is easier to disable it for smartlinking. It doesn't take up
  65. filespace }
  66. result:=not(target_info.system in systems_darwin) and
  67. create_smartlink_sections and
  68. (atype<>sec_toc) and
  69. (atype<>sec_user) and
  70. { on embedded systems every byte counts, so smartlink bss too }
  71. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  72. end;
  73. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  74. const aname: string; aorder: TAsmSectionOrder): string;
  75. const
  76. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  77. '.text',
  78. '.data',
  79. { why doesn't .rodata work? (FK) }
  80. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  81. { vtables (and anything else containing relocations), otherwise those are }
  82. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  83. { vtable for a class called Window: }
  84. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  85. { TODO: .data.ro not yet working}
  86. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  87. '.rodata',
  88. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  89. '.data',
  90. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  91. '.rodata',
  92. '.bss',
  93. '.threadvar',
  94. '.pdata',
  95. '', { stubs }
  96. '__DATA,__nl_symbol_ptr',
  97. '__DATA,__la_symbol_ptr',
  98. '__DATA,__mod_init_func',
  99. '__DATA,__mod_term_func',
  100. '.stab',
  101. '.stabstr',
  102. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  103. '.eh_frame',
  104. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  105. '.fpc',
  106. '.toc',
  107. '.init',
  108. '.fini',
  109. '.objc_class',
  110. '.objc_meta_class',
  111. '.objc_cat_cls_meth',
  112. '.objc_cat_inst_meth',
  113. '.objc_protocol',
  114. '.objc_string_object',
  115. '.objc_cls_meth',
  116. '.objc_inst_meth',
  117. '.objc_cls_refs',
  118. '.objc_message_refs',
  119. '.objc_symbols',
  120. '.objc_category',
  121. '.objc_class_vars',
  122. '.objc_instance_vars',
  123. '.objc_module_info',
  124. '.objc_class_names',
  125. '.objc_meth_var_types',
  126. '.objc_meth_var_names',
  127. '.objc_selector_strs',
  128. '.objc_protocol_ext',
  129. '.objc_class_ext',
  130. '.objc_property',
  131. '.objc_image_info',
  132. '.objc_cstring_object',
  133. '.objc_sel_fixup',
  134. '__DATA,__objc_data',
  135. '__DATA,__objc_const',
  136. '.objc_superrefs',
  137. '__DATA, __datacoal_nt,coalesced',
  138. '.objc_classlist',
  139. '.objc_nlclasslist',
  140. '.objc_catlist',
  141. '.obcj_nlcatlist',
  142. '.objc_protolist',
  143. '.stack',
  144. '.heap',
  145. '.gcc_except_table',
  146. '.ARM.attributes'
  147. );
  148. var
  149. sep : string[3];
  150. secname : string;
  151. begin
  152. secname:=secnames[atype];
  153. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  154. begin
  155. result:=secname+'.'+aname;
  156. exit;
  157. end;
  158. if atype=sec_threadvar then
  159. begin
  160. if (target_info.system in (systems_windows+systems_wince)) then
  161. secname:='.tls'
  162. else if (target_info.system in systems_linux) then
  163. secname:='.tbss';
  164. end;
  165. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  166. Thus, data which normally goes into .rodata and .rodata_norel sections must
  167. end up in .data section }
  168. if (atype in [sec_rodata,sec_rodata_norel]) and
  169. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  170. secname:='.data';
  171. { Windows correctly handles reallocations in readonly sections }
  172. if (atype=sec_rodata) and
  173. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  174. secname:='.rodata';
  175. { section type user gives the user full controll on the section name }
  176. if atype=sec_user then
  177. secname:=aname;
  178. if is_smart_section(atype) and (aname<>'') then
  179. begin
  180. case aorder of
  181. secorder_begin :
  182. sep:='.b_';
  183. secorder_end :
  184. sep:='.z_';
  185. else
  186. sep:='.n_';
  187. end;
  188. result:=secname+sep+aname
  189. end
  190. else
  191. result:=secname;
  192. end;
  193. constructor TWasmObjData.create(const n: string);
  194. begin
  195. inherited;
  196. CObjSection:=TWasmObjSection;
  197. end;
  198. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  199. const aname: string; aorder: TAsmSectionOrder): string;
  200. begin
  201. if (atype=sec_fpc) or (atype=sec_threadvar) then
  202. atype:=sec_data;
  203. Result:=sectionname_gas(atype, aname, aorder);
  204. end;
  205. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  206. p: TObjSymbol; Reloctype: TObjRelocationType);
  207. begin
  208. end;
  209. {****************************************************************************
  210. TWasmObjOutput
  211. ****************************************************************************}
  212. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  213. var
  214. i: Integer;
  215. objsec: TObjSection;
  216. begin
  217. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  218. Writer.write(WasmVersion,SizeOf(WasmVersion));
  219. Writeln('ObjSectionList:');
  220. for i:=0 to Data.ObjSectionList.Count-1 do
  221. begin
  222. objsec:=TObjSection(Data.ObjSectionList[i]);
  223. Writeln(objsec.Name, ' Size=', objsec.Size, ' MemPos=', objsec.MemPos, ' Data.Size=', objsec.Data.size, ' DataPos=', objsec.DataPos);
  224. end;
  225. result:=true;
  226. end;
  227. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  228. begin
  229. inherited;
  230. cobjdata:=TWasmObjData;
  231. end;
  232. {****************************************************************************
  233. TWasmAssembler
  234. ****************************************************************************}
  235. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  236. begin
  237. inherited;
  238. CObjOutput:=TWasmObjOutput;
  239. end;
  240. {*****************************************************************************
  241. Initialize
  242. *****************************************************************************}
  243. {$ifdef wasm32}
  244. const
  245. as_wasm32_wasm_info : tasminfo =
  246. (
  247. id : as_wasm32_wasm;
  248. idtxt : 'OMF';
  249. asmbin : '';
  250. asmcmd : '';
  251. supported_targets : [system_wasm32_embedded,system_wasm32_wasi];
  252. flags : [af_outputbinary,af_smartlink_sections];
  253. labelprefix : '..@';
  254. labelmaxlen : -1;
  255. comment : '; ';
  256. dollarsign: '$';
  257. );
  258. {$endif wasm32}
  259. initialization
  260. {$ifdef wasm32}
  261. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  262. {$endif wasm32}
  263. end.