aggas.pas 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876
  1. {
  2. Copyright (c) 1998-2006 by the Free Pascal team
  3. This unit implements the generic part of the GNU assembler
  4. (v2.8 or later) writer
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. { Base unit for writing GNU assembler output.
  19. }
  20. unit aggas;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,globals,
  25. aasmbase,aasmtai,aasmdata,
  26. assemble;
  27. type
  28. TCPUInstrWriter = class;
  29. {# This is a derived class which is used to write
  30. GAS styled assembler.
  31. }
  32. { TGNUAssembler }
  33. TGNUAssembler=class(texternalassembler)
  34. protected
  35. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
  36. function sectionattrs_coff(atype:TAsmSectiontype):string;virtual;
  37. function sectionalignment_aix(atype:TAsmSectiontype;secalign: byte):string;
  38. procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:byte);
  39. procedure WriteExtraHeader;virtual;
  40. procedure WriteExtraFooter;virtual;
  41. procedure WriteInstruction(hp: tai);
  42. procedure WriteWeakSymbolDef(s: tasmsymbol); virtual;
  43. procedure WriteAixStringConst(hp: tai_string);
  44. procedure WriteAixIntConst(hp: tai_const);
  45. procedure WriteDirectiveName(dir: TAsmDirective); virtual;
  46. public
  47. function MakeCmdLine: TCmdStr; override;
  48. procedure WriteTree(p:TAsmList);override;
  49. procedure WriteAsmList;override;
  50. destructor destroy; override;
  51. private
  52. setcount: longint;
  53. procedure WriteDecodedSleb128(a: int64);
  54. procedure WriteDecodedUleb128(a: qword);
  55. function NextSetLabel: string;
  56. protected
  57. InstrWriter: TCPUInstrWriter;
  58. end;
  59. {# This is the base class for writing instructions.
  60. The WriteInstruction() method must be overridden
  61. to write a single instruction to the assembler
  62. file.
  63. }
  64. TCPUInstrWriter = class
  65. constructor create(_owner: TGNUAssembler);
  66. procedure WriteInstruction(hp : tai); virtual; abstract;
  67. protected
  68. owner: TGNUAssembler;
  69. end;
  70. { TAppleGNUAssembler }
  71. TAppleGNUAssembler=class(TGNUAssembler)
  72. protected
  73. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  74. procedure WriteWeakSymbolDef(s: tasmsymbol); override;
  75. end;
  76. TAoutGNUAssembler=class(TGNUAssembler)
  77. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  78. end;
  79. implementation
  80. uses
  81. SysUtils,
  82. cutils,cfileutl,systems,
  83. fmodule,verbose,
  84. {$ifdef TEST_WIN64_SEH}
  85. itcpugas,
  86. {$endif TEST_WIN64_SEH}
  87. cpubase;
  88. const
  89. line_length = 70;
  90. var
  91. symendcount : longint;
  92. type
  93. {$ifdef cpuextended}
  94. t80bitarray = array[0..9] of byte;
  95. {$endif cpuextended}
  96. t64bitarray = array[0..7] of byte;
  97. t32bitarray = array[0..3] of byte;
  98. {****************************************************************************}
  99. { Support routines }
  100. {****************************************************************************}
  101. function single2str(d : single) : string;
  102. var
  103. hs : string;
  104. begin
  105. str(d,hs);
  106. { replace space with + }
  107. if hs[1]=' ' then
  108. hs[1]:='+';
  109. single2str:='0d'+hs
  110. end;
  111. function double2str(d : double) : string;
  112. var
  113. hs : string;
  114. begin
  115. str(d,hs);
  116. { replace space with + }
  117. if hs[1]=' ' then
  118. hs[1]:='+';
  119. double2str:='0d'+hs
  120. end;
  121. function extended2str(e : extended) : string;
  122. var
  123. hs : string;
  124. begin
  125. str(e,hs);
  126. { replace space with + }
  127. if hs[1]=' ' then
  128. hs[1]:='+';
  129. extended2str:='0d'+hs
  130. end;
  131. { convert floating point values }
  132. { to correct endian }
  133. procedure swap64bitarray(var t: t64bitarray);
  134. var
  135. b: byte;
  136. begin
  137. b:= t[7];
  138. t[7] := t[0];
  139. t[0] := b;
  140. b := t[6];
  141. t[6] := t[1];
  142. t[1] := b;
  143. b:= t[5];
  144. t[5] := t[2];
  145. t[2] := b;
  146. b:= t[4];
  147. t[4] := t[3];
  148. t[3] := b;
  149. end;
  150. procedure swap32bitarray(var t: t32bitarray);
  151. var
  152. b: byte;
  153. begin
  154. b:= t[1];
  155. t[1]:= t[2];
  156. t[2]:= b;
  157. b:= t[0];
  158. t[0]:= t[3];
  159. t[3]:= b;
  160. end;
  161. const
  162. ait_const2str : array[aitconst_128bit..aitconst_half16bit] of string[20]=(
  163. #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
  164. #9'.sleb128'#9,#9'.uleb128'#9,
  165. #9'.rva'#9,#9'.secrel32'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9
  166. );
  167. {****************************************************************************}
  168. { GNU Assembler writer }
  169. {****************************************************************************}
  170. destructor TGNUAssembler.Destroy;
  171. begin
  172. InstrWriter.free;
  173. inherited destroy;
  174. end;
  175. function TGNUAssembler.MakeCmdLine: TCmdStr;
  176. begin
  177. result := inherited MakeCmdLine;
  178. // MWE: disabled again. It generates dwarf info for the generated .s
  179. // files as well. This conflicts with the info we generate
  180. // if target_dbg.id = dbg_dwarf then
  181. // result := result + ' --gdwarf-2';
  182. end;
  183. function TGNUAssembler.NextSetLabel: string;
  184. begin
  185. inc(setcount);
  186. result := target_asm.labelprefix+'$set$'+tostr(setcount);
  187. end;
  188. function is_smart_section(atype:TAsmSectiontype):boolean;
  189. begin
  190. { For bss we need to set some flags that are target dependent,
  191. it is easier to disable it for smartlinking. It doesn't take up
  192. filespace }
  193. result:=not(target_info.system in systems_darwin) and
  194. create_smartlink_sections and
  195. (atype<>sec_toc) and
  196. (atype<>sec_user) and
  197. { on embedded systems every byte counts, so smartlink bss too }
  198. ((atype<>sec_bss) or (target_info.system in systems_embedded));
  199. end;
  200. function TGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  201. const
  202. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  203. '.text',
  204. '.data',
  205. { why doesn't .rodata work? (FK) }
  206. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  207. { vtables (and anything else containing relocations), otherwise those are }
  208. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  209. { vtable for a class called Window: }
  210. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  211. { TODO: .data.ro not yet working}
  212. {$if defined(arm) or defined(powerpc)}
  213. '.rodata',
  214. {$else arm}
  215. '.data',
  216. {$endif arm}
  217. {$if defined(m68k)} { Amiga/m68k GNU AS doesn't seem to like .rodata (KB) }
  218. '.data',
  219. {$else}
  220. '.rodata',
  221. {$endif}
  222. '.bss',
  223. '.threadvar',
  224. '.pdata',
  225. '', { stubs }
  226. '__DATA,__nl_symbol_ptr',
  227. '__DATA,__la_symbol_ptr',
  228. '__DATA,__mod_init_func',
  229. '__DATA,__mod_term_func',
  230. '.stab',
  231. '.stabstr',
  232. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  233. '.eh_frame',
  234. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  235. '.fpc',
  236. '.toc',
  237. '.init',
  238. '.fini',
  239. '.objc_class',
  240. '.objc_meta_class',
  241. '.objc_cat_cls_meth',
  242. '.objc_cat_inst_meth',
  243. '.objc_protocol',
  244. '.objc_string_object',
  245. '.objc_cls_meth',
  246. '.objc_inst_meth',
  247. '.objc_cls_refs',
  248. '.objc_message_refs',
  249. '.objc_symbols',
  250. '.objc_category',
  251. '.objc_class_vars',
  252. '.objc_instance_vars',
  253. '.objc_module_info',
  254. '.objc_class_names',
  255. '.objc_meth_var_types',
  256. '.objc_meth_var_names',
  257. '.objc_selector_strs',
  258. '.objc_protocol_ext',
  259. '.objc_class_ext',
  260. '.objc_property',
  261. '.objc_image_info',
  262. '.objc_cstring_object',
  263. '.objc_sel_fixup',
  264. '__DATA,__objc_data',
  265. '__DATA,__objc_const',
  266. '.objc_superrefs',
  267. '__DATA, __datacoal_nt,coalesced',
  268. '.objc_classlist',
  269. '.objc_nlclasslist',
  270. '.objc_catlist',
  271. '.obcj_nlcatlist',
  272. '.objc_protolist'
  273. );
  274. secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  275. '.text',
  276. '.data.rel',
  277. '.data.rel',
  278. '.data.rel',
  279. '.bss',
  280. '.threadvar',
  281. '.pdata',
  282. '', { stubs }
  283. '__DATA,__nl_symbol_ptr',
  284. '__DATA,__la_symbol_ptr',
  285. '__DATA,__mod_init_func',
  286. '__DATA,__mod_term_func',
  287. '.stab',
  288. '.stabstr',
  289. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  290. '.eh_frame',
  291. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  292. '.fpc',
  293. '.toc',
  294. '.init',
  295. '.fini',
  296. '.objc_class',
  297. '.objc_meta_class',
  298. '.objc_cat_cls_meth',
  299. '.objc_cat_inst_meth',
  300. '.objc_protocol',
  301. '.objc_string_object',
  302. '.objc_cls_meth',
  303. '.objc_inst_meth',
  304. '.objc_cls_refs',
  305. '.objc_message_refs',
  306. '.objc_symbols',
  307. '.objc_category',
  308. '.objc_class_vars',
  309. '.objc_instance_vars',
  310. '.objc_module_info',
  311. '.objc_class_names',
  312. '.objc_meth_var_types',
  313. '.objc_meth_var_names',
  314. '.objc_selector_strs',
  315. '.objc_protocol_ext',
  316. '.objc_class_ext',
  317. '.objc_property',
  318. '.objc_image_info',
  319. '.objc_cstring_object',
  320. '.objc_sel_fixup',
  321. '__DATA, __objc_data',
  322. '__DATA, __objc_const',
  323. '.objc_superrefs',
  324. '__DATA, __datacoal_nt,coalesced',
  325. '.objc_classlist',
  326. '.objc_nlclasslist',
  327. '.objc_catlist',
  328. '.obcj_nlcatlist',
  329. '.objc_protolist'
  330. );
  331. var
  332. sep : string[3];
  333. secname : string;
  334. begin
  335. if (cs_create_pic in current_settings.moduleswitches) and
  336. not(target_info.system in systems_darwin) then
  337. secname:=secnames_pic[atype]
  338. else
  339. secname:=secnames[atype];
  340. {$ifdef m68k}
  341. { old Amiga GNU AS doesn't support .section .fpc }
  342. if (atype=sec_fpc) and (target_info.system = system_m68k_amiga) then
  343. secname:=secnames[sec_data];
  344. {$endif}
  345. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  346. begin
  347. result:=secname+'.'+aname;
  348. exit;
  349. end;
  350. if (atype=sec_threadvar) and
  351. (target_info.system in (systems_windows+systems_wince)) then
  352. secname:='.tls';
  353. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  354. Thus, data which normally goes into .rodata and .rodata_norel sections must
  355. end up in .data section }
  356. if (atype in [sec_rodata,sec_rodata_norel]) and
  357. (target_info.system=system_i386_go32v2) then
  358. secname:='.data';
  359. { section type user gives the user full controll on the section name }
  360. if atype=sec_user then
  361. secname:=aname;
  362. if is_smart_section(atype) and (aname<>'') then
  363. begin
  364. case aorder of
  365. secorder_begin :
  366. sep:='.b_';
  367. secorder_end :
  368. sep:='.z_';
  369. else
  370. sep:='.n_';
  371. end;
  372. result:=secname+sep+aname
  373. end
  374. else
  375. result:=secname;
  376. end;
  377. function TGNUAssembler.sectionattrs_coff(atype:TAsmSectiontype):string;
  378. begin
  379. case atype of
  380. sec_code, sec_init, sec_fini, sec_stub:
  381. result:='x';
  382. { TODO: must be individual for each section }
  383. sec_user:
  384. result:='d';
  385. sec_data, sec_data_lazy, sec_data_nonlazy, sec_fpc,
  386. sec_idata2, sec_idata4, sec_idata5, sec_idata6, sec_idata7:
  387. result:='d';
  388. { TODO: these need a fix to become read-only }
  389. sec_rodata, sec_rodata_norel:
  390. result:='d';
  391. sec_bss:
  392. result:='b';
  393. { TODO: Somewhat questionable. FPC does not allow initialized threadvars,
  394. so no sense to mark it as containing data. But Windows allows it to
  395. contain data, and Linux even has .tdata and .tbss }
  396. sec_threadvar:
  397. result:='b';
  398. sec_pdata, sec_edata, sec_eh_frame, sec_toc:
  399. result:='r';
  400. sec_stab,sec_stabstr,
  401. sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  402. result:='n';
  403. else
  404. result:=''; { defaults to data+load }
  405. end;
  406. end;
  407. function TGNUAssembler.sectionalignment_aix(atype:TAsmSectiontype;secalign: byte): string;
  408. var
  409. l: longint;
  410. begin
  411. if (secalign=0) or
  412. not(atype in [sec_code,sec_bss,sec_rodata_norel,sec_rodata,sec_data]) then
  413. begin
  414. result:='';
  415. exit;
  416. end;
  417. if not ispowerof2(secalign,l) then
  418. internalerror(2012022201);
  419. result:=tostr(l);
  420. end;
  421. procedure TGNUAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:byte);
  422. var
  423. s : string;
  424. begin
  425. AsmLn;
  426. case target_info.system of
  427. system_i386_OS2,
  428. system_i386_EMX,
  429. system_m68k_amiga, { amiga has old GNU AS (2.14), which blews up from .section (KB) }
  430. system_m68k_linux: ;
  431. system_powerpc_darwin,
  432. system_i386_darwin,
  433. system_i386_iphonesim,
  434. system_powerpc64_darwin,
  435. system_x86_64_darwin,
  436. system_arm_darwin,
  437. system_powerpc_aix,
  438. system_powerpc64_aix:
  439. begin
  440. if (atype in [sec_stub,sec_objc_data,sec_objc_const,sec_data_coalesced]) then
  441. AsmWrite('.section ');
  442. end
  443. else
  444. AsmWrite('.section ');
  445. end;
  446. s:=sectionname(atype,aname,aorder);
  447. AsmWrite(s);
  448. case atype of
  449. sec_fpc :
  450. if aname = 'resptrs' then
  451. AsmWrite(', "a", @progbits');
  452. sec_stub :
  453. begin
  454. case target_info.system of
  455. { there are processor-independent shortcuts available }
  456. { for this, namely .symbol_stub and .picsymbol_stub, but }
  457. { they don't work and gcc doesn't use them either... }
  458. system_powerpc_darwin,
  459. system_powerpc64_darwin:
  460. if (cs_create_pic in current_settings.moduleswitches) then
  461. AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
  462. else
  463. AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
  464. system_i386_darwin,
  465. system_i386_iphonesim:
  466. AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
  467. system_arm_darwin:
  468. if (cs_create_pic in current_settings.moduleswitches) then
  469. AsmWriteln('__TEXT,__picsymbolstub4,symbol_stubs,none,16')
  470. else
  471. AsmWriteln('__TEXT,__symbol_stub4,symbol_stubs,none,12')
  472. { darwin/x86-64 uses RIP-based GOT addressing, no symbol stubs }
  473. else
  474. internalerror(2006031101);
  475. end;
  476. end;
  477. else
  478. { GNU AS won't recognize '.text.n_something' section name as belonging
  479. to '.text' and assigns default attributes to it, which is not
  480. always correct. We have to fix it.
  481. TODO: This likely applies to all systems which smartlink without
  482. creating libraries }
  483. if (target_info.system in [system_i386_win32,system_x86_64_win64]) and
  484. is_smart_section(atype) and (aname<>'') then
  485. begin
  486. s:=sectionattrs_coff(atype);
  487. if (s<>'') then
  488. AsmWrite(',"'+s+'"');
  489. end
  490. else if target_info.system in systems_aix then
  491. begin
  492. s:=sectionalignment_aix(atype,secalign);
  493. if s<>'' then
  494. AsmWrite(','+s);
  495. end;
  496. end;
  497. AsmLn;
  498. LastSecType:=atype;
  499. end;
  500. procedure TGNUAssembler.WriteDecodedUleb128(a: qword);
  501. var
  502. i,len : longint;
  503. buf : array[0..63] of byte;
  504. begin
  505. len:=EncodeUleb128(a,buf);
  506. for i:=0 to len-1 do
  507. begin
  508. if (i > 0) then
  509. AsmWrite(',');
  510. AsmWrite(tostr(buf[i]));
  511. end;
  512. end;
  513. procedure TGNUAssembler.WriteDecodedSleb128(a: int64);
  514. var
  515. i,len : longint;
  516. buf : array[0..255] of byte;
  517. begin
  518. len:=EncodeSleb128(a,buf);
  519. for i:=0 to len-1 do
  520. begin
  521. if (i > 0) then
  522. AsmWrite(',');
  523. AsmWrite(tostr(buf[i]));
  524. end;
  525. end;
  526. procedure TGNUAssembler.WriteTree(p:TAsmList);
  527. function needsObject(hp : tai_symbol) : boolean;
  528. begin
  529. needsObject :=
  530. (
  531. assigned(hp.next) and
  532. (tai(hp.next).typ in [ait_const,ait_datablock,
  533. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit])
  534. ) or
  535. (hp.sym.typ=AT_DATA);
  536. end;
  537. procedure doalign(alignment: byte; use_op: boolean; fillop: byte; out last_align: longint);
  538. var
  539. i: longint;
  540. begin
  541. last_align:=alignment;
  542. if alignment>1 then
  543. begin
  544. if not(target_info.system in (systems_darwin+systems_aix)) then
  545. begin
  546. AsmWrite(#9'.balign '+tostr(alignment));
  547. if use_op then
  548. AsmWrite(','+tostr(fillop))
  549. {$ifdef x86}
  550. { force NOP as alignment op code }
  551. else if LastSecType=sec_code then
  552. AsmWrite(',0x90');
  553. {$endif x86}
  554. end
  555. else
  556. begin
  557. { darwin and aix as only support .align }
  558. if not ispowerof2(alignment,i) then
  559. internalerror(2003010305);
  560. AsmWrite(#9'.align '+tostr(i));
  561. last_align:=i;
  562. end;
  563. AsmLn;
  564. end;
  565. end;
  566. var
  567. ch : char;
  568. hp : tai;
  569. constdef : taiconst_type;
  570. s,t : string;
  571. i,pos,l : longint;
  572. InlineLevel : cardinal;
  573. last_align : longint;
  574. co : comp;
  575. sin : single;
  576. d : double;
  577. {$ifdef cpuextended}
  578. e : extended;
  579. {$endif cpuextended}
  580. do_line : boolean;
  581. sepChar : char;
  582. replaceforbidden: boolean;
  583. begin
  584. if not assigned(p) then
  585. exit;
  586. replaceforbidden:=target_asm.dollarsign<>'$';
  587. last_align := 2;
  588. InlineLevel:=0;
  589. { lineinfo is only needed for al_procedures (PFV) }
  590. do_line:=(cs_asm_source in current_settings.globalswitches) or
  591. ((cs_lineinfo in current_settings.moduleswitches)
  592. and (p=current_asmdata.asmlists[al_procedures]));
  593. hp:=tai(p.first);
  594. while assigned(hp) do
  595. begin
  596. prefetch(pointer(hp.next)^);
  597. if not(hp.typ in SkipLineInfo) then
  598. begin
  599. current_filepos:=tailineinfo(hp).fileinfo;
  600. { no line info for inlined code }
  601. if do_line and (inlinelevel=0) then
  602. WriteSourceLine(hp as tailineinfo);
  603. end;
  604. case hp.typ of
  605. ait_comment :
  606. Begin
  607. AsmWrite(target_asm.comment);
  608. AsmWritePChar(tai_comment(hp).str);
  609. AsmLn;
  610. End;
  611. ait_regalloc :
  612. begin
  613. if (cs_asm_regalloc in current_settings.globalswitches) then
  614. begin
  615. AsmWrite(#9+target_asm.comment+'Register ');
  616. repeat
  617. AsmWrite(std_regname(Tai_regalloc(hp).reg));
  618. if (hp.next=nil) or
  619. (tai(hp.next).typ<>ait_regalloc) or
  620. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  621. break;
  622. hp:=tai(hp.next);
  623. AsmWrite(',');
  624. until false;
  625. AsmWrite(' ');
  626. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  627. end;
  628. end;
  629. ait_tempalloc :
  630. begin
  631. if (cs_asm_tempalloc in current_settings.globalswitches) then
  632. WriteTempalloc(tai_tempalloc(hp));
  633. end;
  634. ait_align :
  635. begin
  636. doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,last_align);
  637. end;
  638. ait_section :
  639. begin
  640. if tai_section(hp).sectype<>sec_none then
  641. if replaceforbidden then
  642. WriteSection(tai_section(hp).sectype,ReplaceForbiddenAsmSymbolChars(tai_section(hp).name^),tai_section(hp).secorder,tai_section(hp).secalign)
  643. else
  644. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder,tai_section(hp).secalign)
  645. else
  646. begin
  647. {$ifdef EXTDEBUG}
  648. AsmWrite(target_asm.comment);
  649. AsmWriteln(' sec_none');
  650. {$endif EXTDEBUG}
  651. end;
  652. end;
  653. ait_datablock :
  654. begin
  655. if (target_info.system in systems_darwin) then
  656. begin
  657. { On Mac OS X you can't have common symbols in a shared library
  658. since those are in the TEXT section and the text section is
  659. read-only in shared libraries (so it can be shared among different
  660. processes). The alternate code creates some kind of common symbols
  661. in the data segment.
  662. }
  663. if tai_datablock(hp).is_global then
  664. begin
  665. asmwrite('.globl ');
  666. asmwriteln(tai_datablock(hp).sym.name);
  667. asmwriteln('.data');
  668. asmwrite('.zerofill __DATA, __common, ');
  669. asmwrite(tai_datablock(hp).sym.name);
  670. asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  671. if not(LastSecType in [sec_data,sec_none]) then
  672. writesection(LastSecType,'',secorder_default,1 shl last_align);
  673. end
  674. else
  675. begin
  676. asmwrite(#9'.lcomm'#9);
  677. asmwrite(tai_datablock(hp).sym.name);
  678. asmwrite(','+tostr(tai_datablock(hp).size));
  679. asmwrite(','+tostr(last_align));
  680. asmln;
  681. end;
  682. end
  683. else if target_info.system in systems_aix then
  684. begin
  685. if tai_datablock(hp).is_global then
  686. begin
  687. asmwrite(#9'.globl ');
  688. asmwriteln(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  689. asmwrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  690. asmwriteln(':');
  691. asmwrite(#9'.space ');
  692. asmwriteln(tostr(tai_datablock(hp).size));
  693. if not(LastSecType in [sec_data,sec_none]) then
  694. writesection(LastSecType,'',secorder_default,1 shl last_align);
  695. end
  696. else
  697. begin
  698. asmwrite(#9'.lcomm ');
  699. asmwrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  700. asmwrite(',_data.bss_[RW],');
  701. asmwrite(tostr(tai_datablock(hp).size)+',');
  702. asmwriteln(tostr(last_align));
  703. end;
  704. end
  705. else
  706. begin
  707. {$ifdef USE_COMM_IN_BSS}
  708. if writingpackages then
  709. begin
  710. { The .comm is required for COMMON symbols. These are used
  711. in the shared library loading. All the symbols declared in
  712. the .so file need to resolve to the data allocated in the main
  713. program (PFV) }
  714. if tai_datablock(hp).is_global then
  715. begin
  716. asmwrite(#9'.comm'#9);
  717. if replaceforbidden then
  718. asmwrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name))
  719. else
  720. asmwrite(tai_datablock(hp).sym.name);
  721. asmwrite(','+tostr(tai_datablock(hp).size));
  722. asmwrite(','+tostr(last_align));
  723. asmln;
  724. end
  725. else
  726. begin
  727. asmwrite(#9'.lcomm'#9);
  728. if replaceforbidden then
  729. asmwrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  730. else
  731. asmwrite(tai_datablock(hp).sym.name);
  732. asmwrite(','+tostr(tai_datablock(hp).size));
  733. asmwrite(','+tostr(last_align));
  734. asmln;
  735. end
  736. end
  737. else
  738. {$endif USE_COMM_IN_BSS}
  739. begin
  740. if Tai_datablock(hp).is_global then
  741. begin
  742. asmwrite(#9'.globl ');
  743. if replaceforbidden then
  744. asmwriteln(ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name))
  745. else
  746. asmwriteln(Tai_datablock(hp).sym.name);
  747. end;
  748. if (target_info.system <> system_arm_linux) then
  749. sepChar := '@'
  750. else
  751. sepChar := '%';
  752. if replaceforbidden then
  753. begin
  754. if (tf_needs_symbol_type in target_info.flags) then
  755. asmwriteln(#9'.type '+ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name)+','+sepChar+'object');
  756. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  757. asmwriteln(#9'.size '+ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name)+','+tostr(Tai_datablock(hp).size));
  758. asmwrite(ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name))
  759. end
  760. else
  761. begin
  762. if (tf_needs_symbol_type in target_info.flags) then
  763. asmwriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
  764. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  765. asmwriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  766. asmwrite(Tai_datablock(hp).sym.name);
  767. end;
  768. asmwriteln(':');
  769. asmwriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  770. end;
  771. end;
  772. end;
  773. ait_const:
  774. begin
  775. constdef:=tai_const(hp).consttype;
  776. case constdef of
  777. {$ifndef cpu64bitaddr}
  778. aitconst_128bit :
  779. begin
  780. internalerror(200404291);
  781. end;
  782. aitconst_64bit :
  783. begin
  784. if assigned(tai_const(hp).sym) then
  785. internalerror(200404292);
  786. if not(target_info.system in systems_aix) then
  787. begin
  788. AsmWrite(ait_const2str[aitconst_32bit]);
  789. if target_info.endian = endian_little then
  790. begin
  791. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  792. AsmWrite(',');
  793. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  794. end
  795. else
  796. begin
  797. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  798. AsmWrite(',');
  799. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  800. end;
  801. end
  802. else
  803. WriteAixIntConst(tai_const(hp));
  804. AsmLn;
  805. end;
  806. {$endif cpu64bitaddr}
  807. aitconst_uleb128bit,
  808. aitconst_sleb128bit,
  809. {$ifdef cpu64bitaddr}
  810. aitconst_128bit,
  811. aitconst_64bit,
  812. {$endif cpu64bitaddr}
  813. aitconst_32bit,
  814. aitconst_16bit,
  815. aitconst_8bit,
  816. aitconst_rva_symbol,
  817. aitconst_secrel32_symbol,
  818. aitconst_darwin_dwarf_delta32,
  819. aitconst_darwin_dwarf_delta64,
  820. aitconst_half16bit:
  821. begin
  822. { the AIX assembler (and for compatibility, the GNU
  823. assembler when targeting AIX) automatically aligns
  824. .short/.long/.llong to a multiple of 2/4/8 bytes. We
  825. don't want that, since this may be data inside a packed
  826. record -> use .vbyte instead (byte stream of fixed
  827. length) }
  828. if (target_info.system in systems_aix) and
  829. (constdef in [aitconst_128bit,aitconst_64bit,aitconst_32bit,aitconst_16bit]) and
  830. not assigned(tai_const(hp).sym) then
  831. begin
  832. WriteAixIntConst(tai_const(hp));
  833. end
  834. else if (target_info.system in systems_darwin) and
  835. (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  836. begin
  837. AsmWrite(ait_const2str[aitconst_8bit]);
  838. case tai_const(hp).consttype of
  839. aitconst_uleb128bit:
  840. WriteDecodedUleb128(qword(tai_const(hp).value));
  841. aitconst_sleb128bit:
  842. WriteDecodedSleb128(int64(tai_const(hp).value));
  843. end
  844. end
  845. else
  846. begin
  847. if not(target_info.system in systems_aix) or
  848. (constdef<>aitconst_64bit) then
  849. AsmWrite(ait_const2str[constdef])
  850. else
  851. { can't use .llong, because that forces 8 byte
  852. alignnment and we sometimes store addresses on
  853. 4-byte aligned addresses (e.g. in the RTTI) }
  854. AsmWrite('.vbyte'#9'8,');
  855. l:=0;
  856. t := '';
  857. repeat
  858. if assigned(tai_const(hp).sym) then
  859. begin
  860. if assigned(tai_const(hp).endsym) then
  861. begin
  862. if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
  863. begin
  864. s := NextSetLabel;
  865. t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
  866. end
  867. else
  868. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  869. end
  870. else
  871. s:=tai_const(hp).sym.name;
  872. if replaceforbidden then
  873. s:=ReplaceForbiddenAsmSymbolChars(s);
  874. if tai_const(hp).value<>0 then
  875. s:=s+tostr_with_plus(tai_const(hp).value);
  876. end
  877. else
  878. {$ifdef cpu64bitaddr}
  879. s:=tostr(tai_const(hp).value);
  880. {$else cpu64bitaddr}
  881. { 64 bit constants are already handled above in this case }
  882. s:=tostr(longint(tai_const(hp).value));
  883. {$endif cpu64bitaddr}
  884. if constdef = aitconst_half16bit then
  885. s:='('+s+')/2';
  886. AsmWrite(s);
  887. inc(l,length(s));
  888. { Values with symbols are written on a single line to improve
  889. reading of the .s file (PFV) }
  890. if assigned(tai_const(hp).sym) or
  891. not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
  892. (l>line_length) or
  893. (hp.next=nil) or
  894. (tai(hp.next).typ<>ait_const) or
  895. (tai_const(hp.next).consttype<>constdef) or
  896. assigned(tai_const(hp.next).sym) then
  897. break;
  898. hp:=tai(hp.next);
  899. AsmWrite(',');
  900. until false;
  901. if (t <> '') then
  902. begin
  903. AsmLn;
  904. AsmWrite(t);
  905. end;
  906. end;
  907. AsmLn;
  908. end;
  909. else
  910. internalerror(200704251);
  911. end;
  912. end;
  913. { the "and defined(FPC_HAS_TYPE_EXTENDED)" isn't optimal but currently the only solution
  914. it prevents proper cross compilation to i386 though
  915. }
  916. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  917. ait_real_80bit :
  918. begin
  919. if do_line then
  920. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  921. { Make sure e is a extended type, bestreal could be
  922. a different type (bestreal) !! (PFV) }
  923. e:=tai_real_80bit(hp).value;
  924. AsmWrite(#9'.byte'#9);
  925. for i:=0 to 9 do
  926. begin
  927. if i<>0 then
  928. AsmWrite(',');
  929. AsmWrite(tostr(t80bitarray(e)[i]));
  930. end;
  931. for i:=11 to tai_real_80bit(hp).savesize do
  932. AsmWrite(',0');
  933. AsmLn;
  934. end;
  935. {$endif cpuextended}
  936. ait_real_64bit :
  937. begin
  938. if do_line then
  939. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  940. d:=tai_real_64bit(hp).value;
  941. { swap the values to correct endian if required }
  942. if source_info.endian <> target_info.endian then
  943. swap64bitarray(t64bitarray(d));
  944. AsmWrite(#9'.byte'#9);
  945. {$ifdef arm}
  946. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  947. begin
  948. for i:=4 to 7 do
  949. begin
  950. if i<>4 then
  951. AsmWrite(',');
  952. AsmWrite(tostr(t64bitarray(d)[i]));
  953. end;
  954. for i:=0 to 3 do
  955. begin
  956. AsmWrite(',');
  957. AsmWrite(tostr(t64bitarray(d)[i]));
  958. end;
  959. end
  960. else
  961. {$endif arm}
  962. begin
  963. for i:=0 to 7 do
  964. begin
  965. if i<>0 then
  966. AsmWrite(',');
  967. AsmWrite(tostr(t64bitarray(d)[i]));
  968. end;
  969. end;
  970. AsmLn;
  971. end;
  972. ait_real_32bit :
  973. begin
  974. if do_line then
  975. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  976. sin:=tai_real_32bit(hp).value;
  977. { swap the values to correct endian if required }
  978. if source_info.endian <> target_info.endian then
  979. swap32bitarray(t32bitarray(sin));
  980. AsmWrite(#9'.byte'#9);
  981. for i:=0 to 3 do
  982. begin
  983. if i<>0 then
  984. AsmWrite(',');
  985. AsmWrite(tostr(t32bitarray(sin)[i]));
  986. end;
  987. AsmLn;
  988. end;
  989. ait_comp_64bit :
  990. begin
  991. if do_line then
  992. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  993. AsmWrite(#9'.byte'#9);
  994. co:=comp(tai_comp_64bit(hp).value);
  995. { swap the values to correct endian if required }
  996. if source_info.endian <> target_info.endian then
  997. swap64bitarray(t64bitarray(co));
  998. for i:=0 to 7 do
  999. begin
  1000. if i<>0 then
  1001. AsmWrite(',');
  1002. AsmWrite(tostr(t64bitarray(co)[i]));
  1003. end;
  1004. AsmLn;
  1005. end;
  1006. ait_string :
  1007. begin
  1008. pos:=0;
  1009. if not(target_info.system in systems_aix) then
  1010. begin
  1011. for i:=1 to tai_string(hp).len do
  1012. begin
  1013. if pos=0 then
  1014. begin
  1015. AsmWrite(#9'.ascii'#9'"');
  1016. pos:=20;
  1017. end;
  1018. ch:=tai_string(hp).str[i-1];
  1019. case ch of
  1020. #0, {This can't be done by range, because a bug in FPC}
  1021. #1..#31,
  1022. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  1023. '"' : s:='\"';
  1024. '\' : s:='\\';
  1025. else
  1026. s:=ch;
  1027. end;
  1028. AsmWrite(s);
  1029. inc(pos,length(s));
  1030. if (pos>line_length) or (i=tai_string(hp).len) then
  1031. begin
  1032. AsmWriteLn('"');
  1033. pos:=0;
  1034. end;
  1035. end;
  1036. end
  1037. else
  1038. WriteAixStringConst(tai_string(hp));
  1039. end;
  1040. ait_label :
  1041. begin
  1042. if (tai_label(hp).labsym.is_used) then
  1043. begin
  1044. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  1045. begin
  1046. AsmWrite(#9'.private_extern ');
  1047. AsmWriteln(tai_label(hp).labsym.name);
  1048. end;
  1049. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  1050. begin
  1051. AsmWrite('.globl'#9);
  1052. if replaceforbidden then
  1053. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  1054. else
  1055. AsmWriteLn(tai_label(hp).labsym.name);
  1056. end;
  1057. if replaceforbidden then
  1058. AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  1059. else
  1060. AsmWrite(tai_label(hp).labsym.name);
  1061. AsmWriteLn(':');
  1062. end;
  1063. end;
  1064. ait_symbol :
  1065. begin
  1066. if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
  1067. begin
  1068. AsmWrite(#9'.private_extern ');
  1069. if replaceforbidden then
  1070. AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1071. else
  1072. AsmWriteln(tai_symbol(hp).sym.name);
  1073. end;
  1074. if (target_info.system = system_powerpc64_linux) and
  1075. (tai_symbol(hp).sym.typ = AT_FUNCTION) and (cs_profile in current_settings.moduleswitches) then
  1076. AsmWriteLn('.globl _mcount');
  1077. if tai_symbol(hp).is_global then
  1078. begin
  1079. AsmWrite('.globl'#9);
  1080. if replaceforbidden then
  1081. AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1082. else
  1083. AsmWriteln(tai_symbol(hp).sym.name);
  1084. end;
  1085. if (target_info.system = system_powerpc64_linux) and
  1086. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  1087. begin
  1088. AsmWriteLn('.section ".opd", "aw"');
  1089. AsmWriteLn('.align 3');
  1090. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  1091. AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  1092. AsmWriteLn('.previous');
  1093. AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  1094. if (tai_symbol(hp).is_global) then
  1095. AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  1096. AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  1097. { the dotted name is the name of the actual function entry }
  1098. AsmWrite('.');
  1099. end
  1100. else if (target_info.system in systems_aix) and
  1101. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  1102. begin
  1103. if target_info.system=system_powerpc_aix then
  1104. begin
  1105. s:=#9'.long .';
  1106. ch:='2';
  1107. end
  1108. else
  1109. begin
  1110. s:=#9'.llong .';
  1111. ch:='3';
  1112. end;
  1113. AsmWriteLn(#9'.csect '+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+'[DS],'+ch);
  1114. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+':');
  1115. AsmWriteln(s+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+', TOC[tc0], 0');
  1116. AsmWriteln(#9'.csect .text[PR]');
  1117. if (tai_symbol(hp).is_global) then
  1118. AsmWriteLn('.globl .'+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1119. else
  1120. AsmWriteLn('.lglobl .'+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name));
  1121. { the dotted name is the name of the actual function entry }
  1122. AsmWrite('.');
  1123. end
  1124. else
  1125. begin
  1126. if (target_info.system <> system_arm_linux) then
  1127. sepChar := '@'
  1128. else
  1129. sepChar := '#';
  1130. if (tf_needs_symbol_type in target_info.flags) then
  1131. begin
  1132. AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  1133. if (needsObject(tai_symbol(hp))) then
  1134. AsmWriteLn(',' + sepChar + 'object')
  1135. else
  1136. AsmWriteLn(',' + sepChar + 'function');
  1137. end;
  1138. end;
  1139. if replaceforbidden then
  1140. if not(tai_symbol(hp).has_value) then
  1141. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name + ':'))
  1142. else
  1143. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)))
  1144. else if not(tai_symbol(hp).has_value) then
  1145. AsmWriteLn(tai_symbol(hp).sym.name + ':')
  1146. else
  1147. AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
  1148. end;
  1149. {$ifdef arm}
  1150. ait_thumb_func:
  1151. begin
  1152. AsmWriteLn(#9'.thumb_func');
  1153. end;
  1154. {$endif arm}
  1155. ait_ent:
  1156. begin
  1157. AsmWrite(#9'.ent'#9);
  1158. if replaceforbidden then
  1159. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_ent(hp).Name))
  1160. else
  1161. AsmWriteLn(tai_ent(hp).Name);
  1162. end;
  1163. ait_ent_end:
  1164. begin
  1165. AsmWrite(#9'.end'#9);
  1166. if replaceforbidden then
  1167. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_ent_end(hp).Name))
  1168. else
  1169. AsmWriteLn(tai_ent_end(hp).Name);
  1170. end;
  1171. ait_symbol_end :
  1172. begin
  1173. if tf_needs_symbol_size in target_info.flags then
  1174. begin
  1175. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  1176. inc(symendcount);
  1177. AsmWriteLn(s+':');
  1178. AsmWrite(#9'.size'#9);
  1179. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  1180. AsmWrite('.');
  1181. if replaceforbidden then
  1182. AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_symbol_end(hp).sym.name))
  1183. else
  1184. AsmWrite(tai_symbol_end(hp).sym.name);
  1185. AsmWrite(', '+s+' - ');
  1186. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  1187. AsmWrite('.');
  1188. if replaceforbidden then
  1189. AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol_end(hp).sym.name))
  1190. else
  1191. AsmWriteLn(tai_symbol_end(hp).sym.name);
  1192. end;
  1193. end;
  1194. ait_instruction :
  1195. begin
  1196. WriteInstruction(hp);
  1197. end;
  1198. ait_stab :
  1199. begin
  1200. if assigned(tai_stab(hp).str) then
  1201. begin
  1202. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  1203. AsmWritePChar(tai_stab(hp).str);
  1204. AsmLn;
  1205. end;
  1206. end;
  1207. ait_force_line,
  1208. ait_function_name :
  1209. ;
  1210. ait_cutobject :
  1211. begin
  1212. if SmartAsm then
  1213. begin
  1214. { only reset buffer if nothing has changed }
  1215. if AsmSize=AsmStartSize then
  1216. AsmClear
  1217. else
  1218. begin
  1219. AsmClose;
  1220. DoAssemble;
  1221. AsmCreate(tai_cutobject(hp).place);
  1222. end;
  1223. { avoid empty files }
  1224. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1225. begin
  1226. if tai(hp.next).typ=ait_section then
  1227. LastSecType:=tai_section(hp.next).sectype;
  1228. hp:=tai(hp.next);
  1229. end;
  1230. if LastSecType<>sec_none then
  1231. WriteSection(LastSecType,'',secorder_default,last_align);
  1232. AsmStartSize:=AsmSize;
  1233. end;
  1234. end;
  1235. ait_marker :
  1236. if tai_marker(hp).kind=mark_NoLineInfoStart then
  1237. inc(InlineLevel)
  1238. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  1239. dec(InlineLevel);
  1240. ait_directive :
  1241. begin
  1242. WriteDirectiveName(tai_directive(hp).directive);
  1243. if tai_directive(hp).name <>'' then
  1244. AsmWrite(tai_directive(hp).name);
  1245. AsmLn;
  1246. end;
  1247. ait_seh_directive :
  1248. begin
  1249. {$ifdef TEST_WIN64_SEH}
  1250. AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
  1251. case tai_seh_directive(hp).datatype of
  1252. sd_none:;
  1253. sd_string:
  1254. begin
  1255. AsmWrite(' '+tai_seh_directive(hp).data.name^);
  1256. if (tai_seh_directive(hp).data.flags and 1)<>0 then
  1257. AsmWrite(',@except');
  1258. if (tai_seh_directive(hp).data.flags and 2)<>0 then
  1259. AsmWrite(',@unwind');
  1260. end;
  1261. sd_reg:
  1262. AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
  1263. sd_offset:
  1264. AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
  1265. sd_regoffset:
  1266. AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
  1267. tostr(tai_seh_directive(hp).data.offset));
  1268. end;
  1269. AsmLn;
  1270. {$endif TEST_WIN64_SEH}
  1271. end;
  1272. ait_varloc:
  1273. begin
  1274. if tai_varloc(hp).newlocationhi<>NR_NO then
  1275. AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1276. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation)))
  1277. else
  1278. AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1279. std_regname(tai_varloc(hp).newlocation)));
  1280. AsmLn;
  1281. end;
  1282. else
  1283. internalerror(2006012201);
  1284. end;
  1285. hp:=tai(hp.next);
  1286. end;
  1287. end;
  1288. procedure TGNUAssembler.WriteExtraHeader;
  1289. begin
  1290. end;
  1291. procedure TGNUAssembler.WriteExtraFooter;
  1292. begin
  1293. end;
  1294. procedure TGNUAssembler.WriteInstruction(hp: tai);
  1295. begin
  1296. InstrWriter.WriteInstruction(hp);
  1297. end;
  1298. procedure TGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
  1299. begin
  1300. AsmWriteLn(#9'.weak '+s.name);
  1301. end;
  1302. procedure TGNUAssembler.WriteAixStringConst(hp: tai_string);
  1303. type
  1304. tterminationkind = (term_none,term_string,term_nostring);
  1305. var
  1306. i: longint;
  1307. pos: longint;
  1308. s: string;
  1309. ch: char;
  1310. instring: boolean;
  1311. procedure newstatement(terminationkind: tterminationkind);
  1312. begin
  1313. case terminationkind of
  1314. term_none: ;
  1315. term_string:
  1316. AsmWriteLn('"');
  1317. term_nostring:
  1318. AsmLn;
  1319. end;
  1320. AsmWrite(#9'.byte'#9);
  1321. pos:=20;
  1322. instring:=false;
  1323. end;
  1324. begin
  1325. pos:=0;
  1326. for i:=1 to hp.len do
  1327. begin
  1328. if pos=0 then
  1329. newstatement(term_none);
  1330. ch:=hp.str[i-1];
  1331. case ch of
  1332. #0..#31,
  1333. #127..#255 :
  1334. begin
  1335. if instring then
  1336. newstatement(term_string);
  1337. if pos=20 then
  1338. s:=tostr(ord(ch))
  1339. else
  1340. s:=', '+tostr(ord(ch))
  1341. end;
  1342. '"' :
  1343. if instring then
  1344. s:='""'
  1345. else
  1346. begin
  1347. if pos<>20 then
  1348. newstatement(term_nostring);
  1349. s:='"""';
  1350. instring:=true;
  1351. end;
  1352. else
  1353. if not instring then
  1354. begin
  1355. if (pos<>20) then
  1356. newstatement(term_nostring);
  1357. s:='"'+ch;
  1358. instring:=true;
  1359. end
  1360. else
  1361. s:=ch;
  1362. end;
  1363. AsmWrite(s);
  1364. inc(pos,length(s));
  1365. if (pos>line_length) or (i=tai_string(hp).len) then
  1366. begin
  1367. if instring then
  1368. AsmWriteLn('"')
  1369. else
  1370. AsmLn;
  1371. pos:=0;
  1372. end;
  1373. end;
  1374. end;
  1375. procedure TGNUAssembler.WriteAixIntConst(hp: tai_const);
  1376. var
  1377. pos, size: longint;
  1378. begin
  1379. { only big endian AIX supported for now }
  1380. if target_info.endian<>endian_big then
  1381. internalerror(2012010401);
  1382. { limitation: can only write 4 bytes at a time }
  1383. pos:=0;
  1384. size:=tai_const(hp).size;
  1385. while pos<(size-4) do
  1386. begin
  1387. AsmWrite(#9'.vbyte'#9'4, ');
  1388. AsmWriteln(tostr(longint(tai_const(hp).value shr ((size-pos-4)*8))));
  1389. inc(pos,4);
  1390. end;
  1391. AsmWrite(#9'.vbyte'#9);
  1392. AsmWrite(tostr(size-pos));
  1393. AsmWrite(', ');
  1394. case size-pos of
  1395. 1: AsmWrite(tostr(byte(tai_const(hp).value)));
  1396. 2: AsmWrite(tostr(word(tai_const(hp).value)));
  1397. 4: AsmWrite(tostr(longint(tai_const(hp).value)));
  1398. else
  1399. internalerror(2012010402);
  1400. end;
  1401. end;
  1402. procedure TGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1403. begin
  1404. AsmWrite('.'+directivestr[dir]+' ');
  1405. end;
  1406. procedure TGNUAssembler.WriteAsmList;
  1407. var
  1408. n : string;
  1409. hal : tasmlisttype;
  1410. i: longint;
  1411. begin
  1412. {$ifdef EXTDEBUG}
  1413. if current_module.mainsource<>'' then
  1414. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource);
  1415. {$endif}
  1416. if current_module.mainsource<>'' then
  1417. n:=ExtractFileName(current_module.mainsource)
  1418. else
  1419. n:=InputFileName;
  1420. { gcc does not add it either for Darwin. Grep for
  1421. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  1422. }
  1423. if not(target_info.system in systems_darwin) then
  1424. AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  1425. WriteExtraHeader;
  1426. AsmStartSize:=AsmSize;
  1427. symendcount:=0;
  1428. for hal:=low(TasmlistType) to high(TasmlistType) do
  1429. begin
  1430. AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1431. writetree(current_asmdata.asmlists[hal]);
  1432. AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1433. end;
  1434. { add weak symbol markers }
  1435. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  1436. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  1437. writeweaksymboldef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  1438. if create_smartlink_sections and
  1439. (target_info.system in systems_darwin) then
  1440. AsmWriteLn(#9'.subsections_via_symbols');
  1441. { "no executable stack" marker for Linux }
  1442. if (target_info.system in systems_linux) and
  1443. not(cs_executable_stack in current_settings.moduleswitches) then
  1444. begin
  1445. AsmWriteLn('.section .note.GNU-stack,"",%progbits');
  1446. end;
  1447. AsmLn;
  1448. {$ifdef EXTDEBUG}
  1449. if current_module.mainsource<>'' then
  1450. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
  1451. {$endif EXTDEBUG}
  1452. end;
  1453. {****************************************************************************}
  1454. { Apple/GNU Assembler writer }
  1455. {****************************************************************************}
  1456. function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1457. begin
  1458. if (target_info.system in systems_darwin) then
  1459. case atype of
  1460. sec_bss:
  1461. { all bss (lcomm) symbols are automatically put in the right }
  1462. { place by using the lcomm assembler directive }
  1463. atype := sec_none;
  1464. sec_debug_frame,
  1465. sec_eh_frame:
  1466. begin
  1467. result := '.section __DWARF,__debug_info,regular,debug';
  1468. exit;
  1469. end;
  1470. sec_debug_line:
  1471. begin
  1472. result := '.section __DWARF,__debug_line,regular,debug';
  1473. exit;
  1474. end;
  1475. sec_debug_info:
  1476. begin
  1477. result := '.section __DWARF,__debug_info,regular,debug';
  1478. exit;
  1479. end;
  1480. sec_debug_abbrev:
  1481. begin
  1482. result := '.section __DWARF,__debug_abbrev,regular,debug';
  1483. exit;
  1484. end;
  1485. sec_rodata:
  1486. begin
  1487. result := '.const_data';
  1488. exit;
  1489. end;
  1490. sec_rodata_norel:
  1491. begin
  1492. result := '.const';
  1493. exit;
  1494. end;
  1495. sec_fpc:
  1496. begin
  1497. result := '.section __TEXT, .fpc, regular, no_dead_strip';
  1498. exit;
  1499. end;
  1500. sec_code:
  1501. begin
  1502. if (aname='fpc_geteipasebx') or
  1503. (aname='fpc_geteipasecx') then
  1504. begin
  1505. result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
  1506. #10'.private_extern '+aname;
  1507. exit;
  1508. end;
  1509. end;
  1510. sec_data_nonlazy:
  1511. begin
  1512. result:='.section __DATA, __nl_symbol_ptr,non_lazy_symbol_pointers';
  1513. exit;
  1514. end;
  1515. sec_data_lazy:
  1516. begin
  1517. result:='.section __DATA, __la_symbol_ptr,lazy_symbol_pointers';
  1518. exit;
  1519. end;
  1520. sec_init_func:
  1521. begin
  1522. result:='.section __DATA, __mod_init_func, mod_init_funcs';
  1523. exit;
  1524. end;
  1525. sec_term_func:
  1526. begin
  1527. result:='.section __DATA, __mod_term_func, mod_term_funcs';
  1528. exit;
  1529. end;
  1530. sec_objc_protocol_ext:
  1531. begin
  1532. result:='.section __OBJC, __protocol_ext, regular, no_dead_strip';
  1533. exit;
  1534. end;
  1535. sec_objc_class_ext:
  1536. begin
  1537. result:='.section __OBJC, __class_ext, regular, no_dead_strip';
  1538. exit;
  1539. end;
  1540. sec_objc_property:
  1541. begin
  1542. result:='.section __OBJC, __property, regular, no_dead_strip';
  1543. exit;
  1544. end;
  1545. sec_objc_image_info:
  1546. begin
  1547. result:='.section __OBJC, __image_info, regular, no_dead_strip';
  1548. exit;
  1549. end;
  1550. sec_objc_cstring_object:
  1551. begin
  1552. result:='.section __OBJC, __cstring_object, regular, no_dead_strip';
  1553. exit;
  1554. end;
  1555. sec_objc_sel_fixup:
  1556. begin
  1557. result:='.section __OBJC, __sel_fixup, regular, no_dead_strip';
  1558. exit;
  1559. end;
  1560. sec_objc_message_refs:
  1561. begin
  1562. if (target_info.system in systems_objc_nfabi) then
  1563. begin
  1564. result:='.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip';
  1565. exit;
  1566. end;
  1567. end;
  1568. sec_objc_cls_refs:
  1569. begin
  1570. if (target_info.system in systems_objc_nfabi) then
  1571. begin
  1572. result:='.section __DATA, __objc_clsrefs, regular, no_dead_strip';
  1573. exit;
  1574. end;
  1575. end;
  1576. sec_objc_meth_var_names,
  1577. sec_objc_class_names:
  1578. begin
  1579. if (target_info.system in systems_objc_nfabi) then
  1580. begin
  1581. result:='.cstring';
  1582. exit
  1583. end;
  1584. end;
  1585. sec_objc_inst_meth,
  1586. sec_objc_cls_meth,
  1587. sec_objc_cat_inst_meth,
  1588. sec_objc_cat_cls_meth:
  1589. begin
  1590. if (target_info.system in systems_objc_nfabi) then
  1591. begin
  1592. result:='.section __DATA, __objc_const';
  1593. exit;
  1594. end;
  1595. end;
  1596. sec_objc_meta_class,
  1597. sec_objc_class:
  1598. begin
  1599. if (target_info.system in systems_objc_nfabi) then
  1600. begin
  1601. result:='.section __DATA, __objc_data';
  1602. exit;
  1603. end;
  1604. end;
  1605. sec_objc_sup_refs:
  1606. begin
  1607. result:='.section __DATA, __objc_superrefs, regular, no_dead_strip';
  1608. exit
  1609. end;
  1610. sec_objc_classlist:
  1611. begin
  1612. result:='.section __DATA, __objc_classlist, regular, no_dead_strip';
  1613. exit
  1614. end;
  1615. sec_objc_nlclasslist:
  1616. begin
  1617. result:='.section __DATA, __objc_nlclasslist, regular, no_dead_strip';
  1618. exit
  1619. end;
  1620. sec_objc_catlist:
  1621. begin
  1622. result:='.section __DATA, __objc_catlist, regular, no_dead_strip';
  1623. exit
  1624. end;
  1625. sec_objc_nlcatlist:
  1626. begin
  1627. result:='.section __DATA, __objc_nlcatlist, regular, no_dead_strip';
  1628. exit
  1629. end;
  1630. sec_objc_protolist:
  1631. begin
  1632. result:='.section __DATA, __objc_protolist, coalesced, no_dead_strip';
  1633. exit;
  1634. end;
  1635. end;
  1636. result := inherited sectionname(atype,aname,aorder);
  1637. end;
  1638. procedure TAppleGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
  1639. begin
  1640. AsmWriteLn(#9'.weak_reference '+s.name);
  1641. end;
  1642. {****************************************************************************}
  1643. { a.out/GNU Assembler writer }
  1644. {****************************************************************************}
  1645. function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1646. const
  1647. (* Translation table - replace unsupported section types with basic ones. *)
  1648. SecXTable: array[TAsmSectionType] of TAsmSectionType = (
  1649. sec_none,
  1650. sec_none,
  1651. sec_code,
  1652. sec_data,
  1653. sec_data (* sec_rodata *),
  1654. sec_data (* sec_rodata_norel *),
  1655. sec_bss,
  1656. sec_data (* sec_threadvar *),
  1657. { used for wince exception handling }
  1658. sec_code (* sec_pdata *),
  1659. { used for darwin import stubs }
  1660. sec_code (* sec_stub *),
  1661. sec_data,(* sec_data_nonlazy *)
  1662. sec_data,(* sec_data_lazy *)
  1663. sec_data,(* sec_init_func *)
  1664. sec_data,(* sec_term_func *)
  1665. { stabs }
  1666. sec_stab,sec_stabstr,
  1667. { win32 }
  1668. sec_data (* sec_idata2 *),
  1669. sec_data (* sec_idata4 *),
  1670. sec_data (* sec_idata5 *),
  1671. sec_data (* sec_idata6 *),
  1672. sec_data (* sec_idata7 *),
  1673. sec_data (* sec_edata *),
  1674. { C++ exception handling unwinding (uses dwarf) }
  1675. sec_eh_frame,
  1676. { dwarf }
  1677. sec_debug_frame,
  1678. sec_debug_info,
  1679. sec_debug_line,
  1680. sec_debug_abbrev,
  1681. { ELF resources (+ references to stabs debug information sections) }
  1682. sec_code (* sec_fpc *),
  1683. { Table of contents section }
  1684. sec_code (* sec_toc *),
  1685. sec_code (* sec_init *),
  1686. sec_code (* sec_fini *),
  1687. sec_none (* sec_objc_class *),
  1688. sec_none (* sec_objc_meta_class *),
  1689. sec_none (* sec_objc_cat_cls_meth *),
  1690. sec_none (* sec_objc_cat_inst_meth *),
  1691. sec_none (* sec_objc_protocol *),
  1692. sec_none (* sec_objc_string_object *),
  1693. sec_none (* sec_objc_cls_meth *),
  1694. sec_none (* sec_objc_inst_meth *),
  1695. sec_none (* sec_objc_cls_refs *),
  1696. sec_none (* sec_objc_message_refs *),
  1697. sec_none (* sec_objc_symbols *),
  1698. sec_none (* sec_objc_category *),
  1699. sec_none (* sec_objc_class_vars *),
  1700. sec_none (* sec_objc_instance_vars *),
  1701. sec_none (* sec_objc_module_info *),
  1702. sec_none (* sec_objc_class_names *),
  1703. sec_none (* sec_objc_meth_var_types *),
  1704. sec_none (* sec_objc_meth_var_names *),
  1705. sec_none (* sec_objc_selector_strs *),
  1706. sec_none (* sec_objc_protocol_ext *),
  1707. sec_none (* sec_objc_class_ext *),
  1708. sec_none (* sec_objc_property *),
  1709. sec_none (* sec_objc_image_info *),
  1710. sec_none (* sec_objc_cstring_object *),
  1711. sec_none (* sec_objc_sel_fixup *),
  1712. sec_none (* sec_objc_data *),
  1713. sec_none (* sec_objc_const *),
  1714. sec_none (* sec_objc_sup_refs *),
  1715. sec_none (* sec_data_coalesced *),
  1716. sec_none (* sec_objc_classlist *),
  1717. sec_none (* sec_objc_nlclasslist *),
  1718. sec_none (* sec_objc_catlist *),
  1719. sec_none (* sec_objc_nlcatlist *),
  1720. sec_none (* sec_objc_protlist *)
  1721. );
  1722. begin
  1723. Result := inherited SectionName (SecXTable [AType], AName, AOrder);
  1724. end;
  1725. {****************************************************************************}
  1726. { Abstract Instruction Writer }
  1727. {****************************************************************************}
  1728. constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
  1729. begin
  1730. inherited create;
  1731. owner := _owner;
  1732. end;
  1733. end.