2
0

agllvm.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. {
  2. Copyright (c) 1998-2013 by the Free Pascal team
  3. This unit implements the generic part of the LLVM IR 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 agllvm;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,globals,
  22. aasmbase,aasmtai,aasmdata,
  23. assemble;
  24. type
  25. TLLVMInstrWriter = class;
  26. { TLLVMAssember }
  27. TLLVMAssember=class(texternalassembler)
  28. protected
  29. procedure WriteExtraHeader;virtual;
  30. procedure WriteExtraFooter;virtual;
  31. procedure WriteInstruction(hp: tai);
  32. procedure WriteLlvmInstruction(hp: tai);
  33. // procedure WriteWeakSymbolDef(s: tasmsymbol); virtual;
  34. procedure WriteDirectiveName(dir: TAsmDirective); virtual;
  35. procedure WriteWeakSymbolDef(s: tasmsymbol);
  36. public
  37. constructor create(smart: boolean); override;
  38. function MakeCmdLine: TCmdStr; override;
  39. procedure WriteTree(p:TAsmList);override;
  40. procedure WriteAsmList;override;
  41. destructor destroy; override;
  42. protected
  43. InstrWriter: TLLVMInstrWriter;
  44. end;
  45. {# This is the base class for writing instructions.
  46. The WriteInstruction() method must be overridden
  47. to write a single instruction to the assembler
  48. file.
  49. }
  50. TLLVMInstrWriter = class
  51. constructor create(_owner: TLLVMAssember);
  52. procedure WriteInstruction(hp : tai);
  53. protected
  54. owner: TLLVMAssember;
  55. end;
  56. implementation
  57. uses
  58. SysUtils,
  59. cutils,cfileutl,systems,
  60. fmodule,verbose,
  61. llvmbase,aasmllvm,itllvm,llvmdef,
  62. cgbase,cgutils,cpubase;
  63. const
  64. line_length = 70;
  65. var
  66. symendcount : longint;
  67. type
  68. {$ifdef cpuextended}
  69. t80bitarray = array[0..9] of byte;
  70. {$endif cpuextended}
  71. t64bitarray = array[0..7] of byte;
  72. t32bitarray = array[0..3] of byte;
  73. {****************************************************************************}
  74. { Support routines }
  75. {****************************************************************************}
  76. function single2str(d : single) : string;
  77. var
  78. hs : string;
  79. begin
  80. str(d,hs);
  81. { replace space with + }
  82. if hs[1]=' ' then
  83. hs[1]:='+';
  84. single2str:=hs
  85. end;
  86. function double2str(d : double) : string;
  87. var
  88. hs : string;
  89. begin
  90. str(d,hs);
  91. { replace space with + }
  92. if hs[1]=' ' then
  93. hs[1]:='+';
  94. double2str:=hs
  95. end;
  96. function extended2str(e : extended) : string;
  97. var
  98. hs : string;
  99. begin
  100. str(e,hs);
  101. { replace space with + }
  102. if hs[1]=' ' then
  103. hs[1]:='+';
  104. extended2str:=hs
  105. end;
  106. {****************************************************************************}
  107. { LLVM Instruction writer }
  108. {****************************************************************************}
  109. function getregisterstring(reg: tregister): ansistring;
  110. begin
  111. if getregtype(reg)=R_TEMPREGISTER then
  112. result:='%tmp.'
  113. else
  114. result:='%reg.'+tostr(byte(getregtype(reg)))+'_';
  115. result:=result+tostr(getsupreg(reg));
  116. end;
  117. function getreferencealignstring(var ref: treference) : ansistring;
  118. begin
  119. result:=', align '+tostr(ref.alignment);
  120. end;
  121. function getreferencestring(var ref : treference; withalign: boolean) : ansistring;
  122. begin
  123. result:='';
  124. if assigned(ref.relsymbol) or
  125. (assigned(ref.symbol) =
  126. (ref.base<>NR_NO)) or
  127. (ref.index<>NR_NO) or
  128. (ref.offset<>0) then
  129. begin
  130. result:=' **(error ref: ';
  131. if assigned(ref.symbol) then
  132. result:=result+'sym='+ref.symbol.name+', ';
  133. if assigned(ref.relsymbol) then
  134. result:=result+'sym='+ref.relsymbol.name+', ';
  135. if ref.base=NR_NO then
  136. result:=result+'base=NR_NO, ';
  137. if ref.index<>NR_NO then
  138. result:=result+'index<>NR_NO, ';
  139. if ref.offset<>0 then
  140. result:=result+'offset='+tostr(ref.offset);
  141. result:=result+')**'
  142. // internalerror(2013060225);
  143. end;
  144. if ref.base<>NR_NO then
  145. result:=result+getregisterstring(ref.base)
  146. else
  147. result:=result+ref.symbol.name;
  148. if withalign then
  149. result:=result+getreferencealignstring(ref);
  150. end;
  151. function getopstr(const o:toper; refwithalign: boolean) : ansistring;
  152. var
  153. hs : ansistring;
  154. doubleval: record
  155. case byte of
  156. 1: (d: double);
  157. 2: (i: int64);
  158. end;
  159. {$ifdef cpuextended}
  160. extendedval: record
  161. case byte of
  162. 1: (e: extended);
  163. 2: (r: record
  164. {$ifdef FPC_LITTLE_ENDIAN}
  165. l: int64;
  166. h: word;
  167. {$else FPC_LITTLE_ENDIAN}
  168. h: int64;
  169. l: word;
  170. {$endif FPC_LITTLE_ENDIAN}
  171. end;
  172. );
  173. end;
  174. {$endif cpuextended}
  175. begin
  176. case o.typ of
  177. top_reg:
  178. getopstr:=getregisterstring(o.reg);
  179. top_const:
  180. getopstr:=tostr(longint(o.val));
  181. top_ref:
  182. if o.ref^.refaddr=addr_full then
  183. begin
  184. getopstr:='';
  185. if o.ref^.symbol.typ=AT_LABEL then
  186. getopstr:='label %';
  187. hs:=o.ref^.symbol.name;
  188. if o.ref^.offset<>0 then
  189. internalerror(2013060223);
  190. getopstr:=getopstr+hs;
  191. end
  192. else
  193. getopstr:=getreferencestring(o.ref^,refwithalign);
  194. top_def:
  195. begin
  196. getopstr:=llvmencodetype(o.def);
  197. end;
  198. top_cond:
  199. begin
  200. getopstr:=llvm_cond2str[o.cond];
  201. end;
  202. top_fpcond:
  203. begin
  204. getopstr:=llvm_fpcond2str[o.fpcond];
  205. end;
  206. top_double:
  207. begin
  208. { "When using the hexadecimal form, constants of types half,
  209. float, and double are represented using the 16-digit form shown
  210. above (which matches the IEEE754 representation for double)"
  211. And always in big endian form (sign bit leftmost)
  212. }
  213. doubleval.d:=o.dval;
  214. result:='0x'+hexstr(doubleval.i,16);
  215. end;
  216. {$ifdef cpuextended}
  217. top_extended80:
  218. begin
  219. { hex format is always big endian in llvm }
  220. extendedval.e:=o.eval;
  221. result:='0xK'+hexstr(extendedval.r.h,sizeof(extendedval.r.h)*2)+hexstr(extendedval.r.l,sizeof(extendedval.r.l)*2);
  222. end;
  223. {$endif cpuextended}
  224. else
  225. internalerror(2013060224);
  226. end;
  227. end;
  228. procedure TLlvmInstrWriter.WriteInstruction(hp: tai);
  229. var
  230. op: tllvmop;
  231. s: string;
  232. i, opstart: byte;
  233. sep: string[3];
  234. done: boolean;
  235. begin
  236. op:=taillvm(hp).llvmopcode;
  237. s:=#9;
  238. sep:=' ';
  239. done:=false;
  240. opstart:=0;
  241. case op of
  242. la_ret, la_br, la_switch, la_indirectbr,
  243. la_invoke, la_resume,
  244. la_unreachable,
  245. la_store,
  246. la_fence,
  247. la_cmpxchg,
  248. la_atomicrmw:
  249. begin
  250. { instructions that never have a result }
  251. end;
  252. la_call:
  253. begin
  254. internalerror(2013011601);
  255. end;
  256. la_alloca:
  257. begin
  258. s:=s+getreferencestring(taillvm(hp).oper[0]^.ref^,false)+' = ';
  259. sep:=' ';
  260. opstart:=1;
  261. end;
  262. la_trunc, la_zext, la_sext, la_fptrunc, la_fpext,
  263. la_fptoui, la_fptosi, la_uitofp, la_sitofp,
  264. la_ptrtoint, la_inttoptr,
  265. la_bitcast:
  266. begin
  267. s:=s+getopstr(taillvm(hp).oper[0]^,true)+' = '+
  268. llvm_op2str[op]+' '+
  269. getopstr(taillvm(hp).oper[1]^,true)+' '+
  270. getopstr(taillvm(hp).oper[2]^,true)+' to '+
  271. getopstr(taillvm(hp).oper[3]^,true);
  272. done:=true;
  273. end
  274. else
  275. begin
  276. s:=s+getopstr(taillvm(hp).oper[0]^,true)+' = ';
  277. sep:=' ';
  278. opstart:=1
  279. end;
  280. end;
  281. { process operands }
  282. if not done then
  283. begin
  284. s:=s+llvm_op2str[op];
  285. if taillvm(hp).ops<>0 then
  286. begin
  287. for i:=opstart to taillvm(hp).ops-1 do
  288. begin
  289. s:=s+sep+getopstr(taillvm(hp).oper[i]^,op in [la_load,la_store]);
  290. if taillvm(hp).oper[i]^.typ in [top_def,top_cond,top_fpcond] then
  291. sep :=' '
  292. else
  293. sep:=', ';
  294. end;
  295. end;
  296. end;
  297. if op=la_alloca then
  298. begin
  299. s:=s+getreferencealignstring(taillvm(hp).oper[0]^.ref^)
  300. end;
  301. owner.AsmWriteLn(s);
  302. end;
  303. {****************************************************************************}
  304. { LLVM Assembler writer }
  305. {****************************************************************************}
  306. destructor TLLVMAssember.Destroy;
  307. begin
  308. InstrWriter.free;
  309. inherited destroy;
  310. end;
  311. function TLLVMAssember.MakeCmdLine: TCmdStr;
  312. var
  313. optstr: TCmdStr;
  314. begin
  315. result := inherited MakeCmdLine;
  316. { standard optimization flags for llc -- todo: this needs to be split
  317. into a call to opt and one to llc }
  318. if cs_opt_level3 in current_settings.optimizerswitches then
  319. optstr:='-O3'
  320. else if cs_opt_level2 in current_settings.optimizerswitches then
  321. optstr:='-O2'
  322. else if cs_opt_level1 in current_settings.optimizerswitches then
  323. optstr:='-O1'
  324. else
  325. optstr:='-O0';
  326. { stack frame elimination }
  327. if not(cs_opt_stackframe in current_settings.optimizerswitches) then
  328. optstr:=optstr+' -disable-fp-elim';
  329. { fast math }
  330. if cs_opt_fastmath in current_settings.optimizerswitches then
  331. optstr:=optstr+' -enable-unsafe-fp-math -enable-fp-mad -fp-contract=fast';
  332. { smart linking }
  333. if cs_create_smart in current_settings.moduleswitches then
  334. optstr:=optstr+' -fdata-sections -fcode-sections';
  335. { pic }
  336. if cs_create_pic in current_settings.moduleswitches then
  337. optstr:=optstr+' -relocation-model=pic'
  338. else if not(target_info.system in systems_darwin) then
  339. optstr:=optstr+' -relocation-model=static'
  340. else
  341. optstr:=optstr+' -relocation-model=dynamic-no-pic';
  342. { our stack alignment is non-standard on some targets. The following
  343. parameter is however ignored on some targets by llvm, so it may not
  344. be enough }
  345. optstr:=optstr+' -stack-alignment='+tostr(target_info.stackalign*8);
  346. { force object output instead of textual assembler code }
  347. optstr:=optstr+' -filetype=obj';
  348. replace(result,'$OPT',optstr);
  349. end;
  350. procedure TLLVMAssember.WriteTree(p:TAsmList);
  351. var
  352. ch : char;
  353. lasthp,
  354. hp : tai;
  355. constdef : taiconst_type;
  356. s,t : string;
  357. i,pos,l : longint;
  358. InlineLevel : cardinal;
  359. last_align : longint;
  360. co : comp;
  361. sin : single;
  362. d : double;
  363. {$ifdef cpuextended}
  364. e : extended;
  365. {$endif cpuextended}
  366. do_line : boolean;
  367. sepChar : char;
  368. replaceforbidden: boolean;
  369. begin
  370. if not assigned(p) then
  371. exit;
  372. replaceforbidden:=target_asm.dollarsign<>'$';
  373. last_align := 2;
  374. InlineLevel:=0;
  375. { lineinfo is only needed for al_procedures (PFV) }
  376. do_line:=(cs_asm_source in current_settings.globalswitches) or
  377. ((cs_lineinfo in current_settings.moduleswitches)
  378. and (p=current_asmdata.asmlists[al_procedures]));
  379. lasthp:=nil;
  380. hp:=tai(p.first);
  381. while assigned(hp) do
  382. begin
  383. prefetch(pointer(hp.next)^);
  384. if not(hp.typ in SkipLineInfo) then
  385. begin
  386. current_filepos:=tailineinfo(hp).fileinfo;
  387. { no line info for inlined code }
  388. if do_line and (inlinelevel=0) then
  389. WriteSourceLine(hp as tailineinfo);
  390. end;
  391. case hp.typ of
  392. ait_comment :
  393. Begin
  394. AsmWrite(target_asm.comment);
  395. AsmWritePChar(tai_comment(hp).str);
  396. AsmLn;
  397. End;
  398. ait_regalloc :
  399. begin
  400. if (cs_asm_regalloc in current_settings.globalswitches) then
  401. begin
  402. AsmWrite(#9+target_asm.comment+'Register ');
  403. repeat
  404. AsmWrite(std_regname(Tai_regalloc(hp).reg));
  405. if (hp.next=nil) or
  406. (tai(hp.next).typ<>ait_regalloc) or
  407. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  408. break;
  409. hp:=tai(hp.next);
  410. AsmWrite(',');
  411. until false;
  412. AsmWrite(' ');
  413. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  414. end;
  415. end;
  416. ait_tempalloc :
  417. begin
  418. if (cs_asm_tempalloc in current_settings.globalswitches) then
  419. WriteTempalloc(tai_tempalloc(hp));
  420. end;
  421. ait_align :
  422. begin
  423. { has to be specified as part of the symbol declaration }
  424. AsmWriteln('; error: explicit aligns are forbidden');
  425. // internalerror(2013010714);
  426. end;
  427. ait_section :
  428. begin
  429. AsmWrite(target_asm.comment);
  430. AsmWriteln('section');
  431. end;
  432. ait_datablock :
  433. begin
  434. AsmWrite(target_asm.comment);
  435. AsmWriteln('datablock');
  436. end;
  437. ait_const:
  438. begin
  439. AsmWrite(target_asm.comment);
  440. AsmWriteln('const');
  441. end;
  442. { the "and defined(FPC_HAS_TYPE_EXTENDED)" isn't optimal but currently the only solution
  443. it prevents proper cross compilation to i386 though
  444. }
  445. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  446. ait_real_80bit :
  447. begin
  448. // if do_line then
  449. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  450. end;
  451. {$endif cpuextended}
  452. ait_real_32bit,
  453. ait_real_64bit:
  454. begin
  455. if hp.typ=ait_real_32bit then
  456. begin
  457. // if do_line then
  458. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  459. // d:=tai_real_32bit(hp).value
  460. end
  461. else
  462. begin
  463. // if do_line then
  464. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  465. // d:=tai_real_64bit(hp).value;
  466. end;
  467. end;
  468. ait_comp_64bit :
  469. begin
  470. // if do_line then
  471. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  472. end;
  473. ait_string :
  474. begin
  475. AsmWrite(target_asm.comment);
  476. AsmWriteln('string');
  477. end;
  478. ait_label :
  479. begin
  480. if (tai_label(hp).labsym.is_used) then
  481. begin
  482. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  483. begin
  484. { should be emitted as part of the variable/function def }
  485. internalerror(2013010703);
  486. end;
  487. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  488. begin
  489. { should be emitted as part of the variable/function def }
  490. internalerror(2013010704);
  491. end;
  492. if replaceforbidden then
  493. AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  494. else
  495. AsmWrite(tai_label(hp).labsym.name);
  496. AsmWriteLn(':');
  497. end;
  498. end;
  499. ait_symbol :
  500. begin
  501. { should be emitted as part of the variable/function def }
  502. asmwrite('; (ait_symbol error, should be part of variable/function def) :');
  503. asmwriteln(tai_symbol(hp).sym.name);
  504. // internalerror(2013010705);
  505. end;
  506. ait_llvmprocdef:
  507. begin
  508. asmwrite('define ');
  509. asmwrite(llvmencodeproctype(taillvmprocdef(hp).procdef,true,true));
  510. asmwriteln(' {');
  511. end;
  512. ait_llvmvarsym:
  513. begin
  514. asmwrite(taillvmvarsym(hp).varsym.mangledname);
  515. if not taillvmvarsym(hp).varsym.globalasmsym then
  516. asmwrite(' = internal global ')
  517. else
  518. asmwrite(' = global ');
  519. asmwrite(llvmencodetype(taillvmvarsym(hp).varsym.vardef));
  520. asmwrite(' zeroinitializer, align ');
  521. asmwriteln(tostr(taillvmvarsym(hp).varsym.vardef.alignment));
  522. end;
  523. ait_llvmalias:
  524. begin
  525. asmwrite(taillvmalias(hp).newsym.name);
  526. asmwrite(' = ');
  527. if taillvmalias(hp).linkage<>lll_default then
  528. begin
  529. str(taillvmalias(hp).linkage,s);
  530. asmwrite(copy(s,length('lll_'),255));
  531. asmwrite(' ');
  532. end;
  533. if taillvmalias(hp).vis<>llv_default then
  534. begin
  535. str(taillvmalias(hp).vis,s);
  536. asmwrite(copy(s,length('llv_'),255));
  537. asmwrite(' ');
  538. end;
  539. asmwrite(llvmencodetype(taillvmalias(hp).def));
  540. asmwrite(' ');
  541. asmwriteln(taillvmalias(hp).oldsym.name);
  542. end;
  543. {$ifdef arm}
  544. ait_thumb_func:
  545. begin
  546. { should be emitted as part of the function def }
  547. internalerror(2013010706);
  548. end;
  549. ait_thumb_set:
  550. begin
  551. { should be emitted as part of the symbol def }
  552. internalerror(2013010707);
  553. end;
  554. {$endif arm}
  555. ait_set:
  556. begin
  557. { should be emitted as part of the symbol def }
  558. internalerror(2013010708);
  559. end;
  560. ait_weak:
  561. begin
  562. { should be emitted as part of the symbol def }
  563. internalerror(2013010709);
  564. end;
  565. ait_symbol_end :
  566. begin
  567. if tai_symbol_end(hp).sym.typ=AT_FUNCTION then
  568. asmwriteln('}')
  569. else
  570. asmwriteln('; ait_symbol_end error, should not be generated');
  571. // internalerror(2013010711);
  572. end;
  573. ait_instruction :
  574. begin
  575. WriteInstruction(hp);
  576. end;
  577. ait_llvmins:
  578. begin
  579. WriteLlvmInstruction(hp);
  580. end;
  581. ait_stab :
  582. begin
  583. internalerror(2013010712);
  584. end;
  585. ait_force_line,
  586. ait_function_name :
  587. ;
  588. ait_cutobject :
  589. begin
  590. end;
  591. ait_marker :
  592. if tai_marker(hp).kind=mark_NoLineInfoStart then
  593. inc(InlineLevel)
  594. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  595. dec(InlineLevel);
  596. ait_directive :
  597. begin
  598. WriteDirectiveName(tai_directive(hp).directive);
  599. if tai_directive(hp).name <>'' then
  600. AsmWrite(tai_directive(hp).name);
  601. AsmLn;
  602. end;
  603. ait_seh_directive :
  604. begin
  605. internalerror(2013010713);
  606. end;
  607. ait_varloc:
  608. begin
  609. if tai_varloc(hp).newlocationhi<>NR_NO then
  610. AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  611. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation)))
  612. else
  613. AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  614. std_regname(tai_varloc(hp).newlocation)));
  615. AsmLn;
  616. end;
  617. else
  618. internalerror(2006012201);
  619. end;
  620. lasthp:=hp;
  621. hp:=tai(hp.next);
  622. end;
  623. end;
  624. procedure TLLVMAssember.WriteExtraHeader;
  625. begin
  626. AsmWrite('target datalayout = "');
  627. AsmWrite(target_info.llvmdatalayout);
  628. AsmWriteln('"');
  629. AsmWrite('target triple = "');
  630. AsmWrite(llvm_target_name);
  631. AsmWriteln('"');
  632. end;
  633. procedure TLLVMAssember.WriteExtraFooter;
  634. begin
  635. end;
  636. procedure TLLVMAssember.WriteInstruction(hp: tai);
  637. begin
  638. end;
  639. procedure TLLVMAssember.WriteLlvmInstruction(hp: tai);
  640. begin
  641. InstrWriter.WriteInstruction(hp);
  642. end;
  643. procedure TLLVMAssember.WriteWeakSymbolDef(s: tasmsymbol);
  644. begin
  645. AsmWriteLn(#9'.weak '+s.name);
  646. end;
  647. constructor TLLVMAssember.create(smart: boolean);
  648. begin
  649. inherited create(smart);
  650. InstrWriter:=TLLVMInstrWriter.create(self);
  651. end;
  652. procedure TLLVMAssember.WriteDirectiveName(dir: TAsmDirective);
  653. begin
  654. AsmWrite('.'+directivestr[dir]+' ');
  655. end;
  656. procedure TLLVMAssember.WriteAsmList;
  657. var
  658. n : string;
  659. hal : tasmlisttype;
  660. i: longint;
  661. begin
  662. if current_module.mainsource<>'' then
  663. n:=ExtractFileName(current_module.mainsource)
  664. else
  665. n:=InputFileName;
  666. { gcc does not add it either for Darwin. Grep for
  667. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  668. }
  669. if not(target_info.system in systems_darwin) then
  670. AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  671. WriteExtraHeader;
  672. AsmStartSize:=AsmSize;
  673. symendcount:=0;
  674. for hal:=low(TasmlistType) to high(TasmlistType) do
  675. begin
  676. AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  677. writetree(current_asmdata.asmlists[hal]);
  678. AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
  679. end;
  680. { add weak symbol markers }
  681. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  682. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  683. writeweaksymboldef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  684. AsmLn;
  685. end;
  686. {****************************************************************************}
  687. { Abstract Instruction Writer }
  688. {****************************************************************************}
  689. constructor TLLVMInstrWriter.create(_owner: TLLVMAssember);
  690. begin
  691. inherited create;
  692. owner := _owner;
  693. end;
  694. const
  695. as_llvm_info : tasminfo =
  696. (
  697. id : as_llvm;
  698. idtxt : 'LLVM-AS';
  699. asmbin : 'llc';
  700. asmcmd: '$OPT -o $OBJ $ASM';
  701. supported_targets : [system_x86_64_linux,system_x86_64_darwin];
  702. flags : [af_smartlink_sections];
  703. labelprefix : 'L';
  704. comment : '; ';
  705. dollarsign: '$';
  706. );
  707. begin
  708. RegisterAssembler(as_llvm_info,TLLVMAssember);
  709. end.