ogwasm.pas 9.5 KB

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