agllvm.pas 26 KB

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