2
0

agllvm.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  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,systems,
  22. aasmbase,aasmtai,aasmdata,
  23. assemble;
  24. type
  25. TLLVMInstrWriter = class;
  26. TLLVMBaseInlineAssemblyDecorator = class
  27. function LineFilter(const s: AnsiString): AnsiString;
  28. end;
  29. TLLVMModuleInlineAssemblyDecorator = class(TLLVMBaseInlineAssemblyDecorator,IExternalAssemblerOutputFileDecorator)
  30. function LinePrefix: AnsiString;
  31. function LinePostfix: AnsiString;
  32. function LineEnding(const deflineending: ShortString): ShortString;
  33. end;
  34. TLLVMFunctionInlineAssemblyDecorator = class(TLLVMBaseInlineAssemblyDecorator,IExternalAssemblerOutputFileDecorator)
  35. function LinePrefix: AnsiString;
  36. function LinePostfix: AnsiString;
  37. function LineEnding(const deflineending: ShortString): ShortString;
  38. end;
  39. TLLVMAssember=class(texternalassembler)
  40. protected
  41. fdecllevel: longint;
  42. procedure WriteExtraHeader;virtual;
  43. procedure WriteExtraFooter;virtual;
  44. procedure WriteInstruction(hp: tai);
  45. procedure WriteLlvmInstruction(hp: tai);
  46. procedure WriteDirectiveName(dir: TAsmDirective); virtual;
  47. procedure WriteRealConst(hp: tai_realconst; do_line: boolean);
  48. procedure WriteOrdConst(hp: tai_const);
  49. procedure WriteTai(const replaceforbidden: boolean; const do_line: boolean; var InlineLevel: cardinal; var asmblock: boolean; var hp: tai);
  50. public
  51. constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
  52. function MakeCmdLine: TCmdStr; override;
  53. procedure WriteTree(p:TAsmList);override;
  54. procedure WriteAsmList;override;
  55. destructor destroy; override;
  56. protected
  57. InstrWriter: TLLVMInstrWriter;
  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. TLLVMInstrWriter = class
  65. constructor create(_owner: TLLVMAssember);
  66. procedure WriteInstruction(hp : tai);
  67. protected
  68. owner: TLLVMAssember;
  69. fstr: TSymStr;
  70. function getopstr(const o:toper; refwithalign: boolean) : TSymStr;
  71. end;
  72. implementation
  73. uses
  74. SysUtils,
  75. cutils,cfileutl,
  76. fmodule,verbose,
  77. objcasm,
  78. aasmcnst,symconst,symdef,symtable,
  79. llvmbase,aasmllvm,itllvm,llvmdef,
  80. cgbase,cgutils,cpubase,llvminfo;
  81. const
  82. line_length = 70;
  83. type
  84. {$ifdef cpuextended}
  85. t80bitarray = array[0..9] of byte;
  86. {$endif cpuextended}
  87. t64bitarray = array[0..7] of byte;
  88. t32bitarray = array[0..3] of byte;
  89. {****************************************************************************}
  90. { Support routines }
  91. {****************************************************************************}
  92. function single2str(d : single) : string;
  93. var
  94. hs : string;
  95. begin
  96. str(d,hs);
  97. { replace space with + }
  98. if hs[1]=' ' then
  99. hs[1]:='+';
  100. single2str:=hs
  101. end;
  102. function double2str(d : double) : string;
  103. var
  104. hs : string;
  105. begin
  106. str(d,hs);
  107. { replace space with + }
  108. if hs[1]=' ' then
  109. hs[1]:='+';
  110. double2str:=hs
  111. end;
  112. function extended2str(e : extended) : string;
  113. var
  114. hs : string;
  115. begin
  116. str(e,hs);
  117. { replace space with + }
  118. if hs[1]=' ' then
  119. hs[1]:='+';
  120. extended2str:=hs
  121. end;
  122. {****************************************************************************}
  123. { Common decorator functionality for inline assembly }
  124. {****************************************************************************}
  125. function TLLVMBaseInlineAssemblyDecorator.LineFilter(const s: AnsiString): AnsiString;
  126. var
  127. i: longint;
  128. begin
  129. result:='';
  130. for i:=1 to length(s) do
  131. begin
  132. case s[i] of
  133. #0..#31,
  134. #127..#255,
  135. '"','\':
  136. result:=result+
  137. '\'+
  138. chr((ord(s[i]) shr 4)+ord('0'))+
  139. chr((ord(s[i]) and $f)+ord('0'));
  140. else
  141. result:=result+s[i];
  142. end;
  143. end;
  144. end;
  145. {****************************************************************************}
  146. { Decorator for module-level inline assembly }
  147. {****************************************************************************}
  148. function TLLVMModuleInlineAssemblyDecorator.LinePrefix: AnsiString;
  149. begin
  150. result:='module asm "';
  151. end;
  152. function TLLVMModuleInlineAssemblyDecorator.LinePostfix: AnsiString;
  153. begin
  154. result:='"';
  155. end;
  156. function TLLVMModuleInlineAssemblyDecorator.LineEnding(const deflineending: ShortString): ShortString;
  157. begin
  158. result:=deflineending
  159. end;
  160. {****************************************************************************}
  161. { Decorator for function-level inline assembly }
  162. {****************************************************************************}
  163. function TLLVMFunctionInlineAssemblyDecorator.LinePrefix: AnsiString;
  164. begin
  165. result:='';
  166. end;
  167. function TLLVMFunctionInlineAssemblyDecorator.LinePostfix: AnsiString;
  168. begin
  169. result:='';
  170. end;
  171. function TLLVMFunctionInlineAssemblyDecorator.LineEnding(const deflineending: ShortString): ShortString;
  172. begin
  173. result:='\0A';
  174. end;
  175. {****************************************************************************}
  176. { LLVM Instruction writer }
  177. {****************************************************************************}
  178. function getregisterstring(reg: tregister): ansistring;
  179. begin
  180. if getregtype(reg)=R_TEMPREGISTER then
  181. result:='%tmp.'
  182. else
  183. result:='%reg.'+tostr(byte(getregtype(reg)))+'_';
  184. result:=result+tostr(getsupreg(reg));
  185. end;
  186. function getreferencealignstring(var ref: treference) : ansistring;
  187. begin
  188. result:=', align '+tostr(ref.alignment);
  189. end;
  190. function getreferencestring(var ref : treference; withalign: boolean) : ansistring;
  191. begin
  192. result:='';
  193. if assigned(ref.relsymbol) or
  194. (assigned(ref.symbol) and
  195. (ref.base<>NR_NO)) or
  196. (ref.index<>NR_NO) or
  197. (ref.offset<>0) then
  198. begin
  199. result:=' **(error ref: ';
  200. if assigned(ref.symbol) then
  201. result:=result+'sym='+ref.symbol.name+', ';
  202. if assigned(ref.relsymbol) then
  203. result:=result+'sym='+ref.relsymbol.name+', ';
  204. if ref.base=NR_NO then
  205. result:=result+'base=NR_NO, ';
  206. if ref.index<>NR_NO then
  207. result:=result+'index<>NR_NO, ';
  208. if ref.offset<>0 then
  209. result:=result+'offset='+tostr(ref.offset);
  210. result:=result+')**';
  211. internalerror(2013060225);
  212. end;
  213. if ref.base<>NR_NO then
  214. result:=result+getregisterstring(ref.base)
  215. else if assigned(ref.symbol) then
  216. result:=result+LlvmAsmSymName(ref.symbol)
  217. else
  218. result:=result+'null';
  219. if withalign then
  220. result:=result+getreferencealignstring(ref);
  221. end;
  222. function getparas(const paras: tfplist): ansistring;
  223. var
  224. i: longint;
  225. para: pllvmcallpara;
  226. begin
  227. result:='(';
  228. for i:=0 to paras.count-1 do
  229. begin
  230. if i<>0 then
  231. result:=result+', ';
  232. para:=pllvmcallpara(paras[i]);
  233. result:=result+llvmencodetypename(para^.def);
  234. if para^.valueext<>lve_none then
  235. result:=result+llvmvalueextension2str[para^.valueext];
  236. if para^.byval then
  237. result:=result+' byval';
  238. if para^.sret then
  239. result:=result+' sret';
  240. case para^.loc of
  241. LOC_REGISTER,
  242. LOC_FPUREGISTER,
  243. LOC_MMREGISTER:
  244. result:=result+' '+getregisterstring(para^.reg);
  245. LOC_CONSTANT:
  246. result:=result+' '+tostr(int64(para^.value));
  247. { empty records }
  248. LOC_VOID:
  249. result:=result+' undef';
  250. else
  251. internalerror(2014010801);
  252. end;
  253. end;
  254. result:=result+')';
  255. end;
  256. function llvmdoubletostr(const d: double): TSymStr;
  257. type
  258. tdoubleval = record
  259. case byte of
  260. 1: (d: double);
  261. 2: (i: int64);
  262. end;
  263. begin
  264. { "When using the hexadecimal form, constants of types half,
  265. float, and double are represented using the 16-digit form shown
  266. above (which matches the IEEE754 representation for double)"
  267. And always in big endian form (sign bit leftmost)
  268. }
  269. result:='0x'+hexstr(tdoubleval(d).i,16);
  270. end;
  271. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  272. function llvmextendedtostr(const e: extended): TSymStr;
  273. var
  274. extendedval: record
  275. case byte of
  276. 1: (e: extended);
  277. 2: (r: packed record
  278. {$ifdef FPC_LITTLE_ENDIAN}
  279. l: int64;
  280. h: word;
  281. {$else FPC_LITTLE_ENDIAN}
  282. h: int64;
  283. l: word;
  284. {$endif FPC_LITTLE_ENDIAN}
  285. end;
  286. );
  287. end;
  288. begin
  289. extendedval.e:=e;
  290. { hex format is always big endian in llvm }
  291. result:='0xK'+hexstr(extendedval.r.h,sizeof(extendedval.r.h)*2)+
  292. hexstr(extendedval.r.l,sizeof(extendedval.r.l)*2);
  293. end;
  294. {$endif cpuextended}
  295. function TLLVMInstrWriter.getopstr(const o:toper; refwithalign: boolean) : TSymStr;
  296. var
  297. hs : ansistring;
  298. hp: tai;
  299. tmpinline: cardinal;
  300. tmpasmblock: boolean;
  301. begin
  302. case o.typ of
  303. top_reg:
  304. getopstr:=getregisterstring(o.reg);
  305. top_const:
  306. getopstr:=tostr(int64(o.val));
  307. top_ref:
  308. if o.ref^.refaddr=addr_full then
  309. begin
  310. getopstr:='';
  311. getopstr:=LlvmAsmSymName(o.ref^.symbol);
  312. if o.ref^.offset<>0 then
  313. internalerror(2013060223);
  314. end
  315. else
  316. getopstr:=getreferencestring(o.ref^,refwithalign);
  317. top_def:
  318. begin
  319. getopstr:=llvmencodetypename(o.def);
  320. end;
  321. top_cond:
  322. begin
  323. getopstr:=llvm_cond2str[o.cond];
  324. end;
  325. top_fpcond:
  326. begin
  327. getopstr:=llvm_fpcond2str[o.fpcond];
  328. end;
  329. top_single,
  330. top_double:
  331. begin
  332. { "When using the hexadecimal form, constants of types half,
  333. float, and double are represented using the 16-digit form shown
  334. above (which matches the IEEE754 representation for double)"
  335. And always in big endian form (sign bit leftmost)
  336. }
  337. if o.typ=top_double then
  338. result:=llvmdoubletostr(o.dval)
  339. else
  340. result:=llvmdoubletostr(o.sval)
  341. end;
  342. top_para:
  343. begin
  344. result:=getparas(o.paras);
  345. end;
  346. top_tai:
  347. begin
  348. tmpinline:=1;
  349. tmpasmblock:=false;
  350. hp:=o.ai;
  351. owner.writer.AsmWrite(fstr);
  352. fstr:='';
  353. owner.WriteTai(false,false,tmpinline,tmpasmblock,hp);
  354. result:='';
  355. end;
  356. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  357. top_extended80:
  358. begin
  359. result:=llvmextendedtostr(o.eval);
  360. end;
  361. {$endif cpuextended}
  362. top_undef:
  363. result:='undef'
  364. else
  365. internalerror(2013060227);
  366. end;
  367. end;
  368. procedure TLLVMInstrWriter.WriteInstruction(hp: tai);
  369. var
  370. op: tllvmop;
  371. tmpstr,
  372. sep: TSymStr;
  373. i, opstart: byte;
  374. nested: boolean;
  375. opdone,
  376. done: boolean;
  377. begin
  378. op:=taillvm(hp).llvmopcode;
  379. { we write everything immediately rather than adding it into a string,
  380. because operands may contain other tai that will also write things out
  381. (and their output must come after everything that was processed in this
  382. instruction, such as its opcode or previous operands) }
  383. if owner.fdecllevel=0 then
  384. owner.writer.AsmWrite(#9);
  385. sep:=' ';
  386. opdone:=false;
  387. done:=false;
  388. opstart:=0;
  389. nested:=false;
  390. case op of
  391. la_type:
  392. begin
  393. owner.writer.AsmWrite(llvmtypeidentifier(taillvm(hp).oper[0]^.def));
  394. owner.writer.AsmWrite(' = type ');
  395. owner.writer.AsmWrite(llvmencodetypedecl(taillvm(hp).oper[0]^.def));
  396. done:=true;
  397. end;
  398. la_load,
  399. la_getelementptr:
  400. begin
  401. if (taillvm(hp).oper[0]^.typ<>top_reg) or
  402. (taillvm(hp).oper[0]^.reg<>NR_NO) then
  403. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[0]^,false)+' = ')
  404. else
  405. nested:=true;
  406. opstart:=1;
  407. if llvmflag_load_getelptr_type in llvmversion_properties[current_settings.llvmversion] then
  408. begin
  409. owner.writer.AsmWrite(llvm_op2str[op]);
  410. opdone:=true;
  411. if nested then
  412. owner.writer.AsmWrite(' (')
  413. else
  414. owner.writer.AsmWrite(' ');
  415. { can't just dereference the type, because it may be an
  416. implicit pointer type such as a class -> resort to string
  417. manipulation... Not very clean :( }
  418. tmpstr:=llvmencodetypename(taillvm(hp).spilling_get_reg_type(0));
  419. if op=la_getelementptr then
  420. begin
  421. if tmpstr[length(tmpstr)]<>'*' then
  422. begin
  423. writeln(tmpstr);
  424. internalerror(2016071101);
  425. end
  426. else
  427. setlength(tmpstr,length(tmpstr)-1);
  428. end;
  429. owner.writer.AsmWrite(tmpstr);
  430. owner.writer.AsmWrite(',');
  431. end
  432. end;
  433. la_ret, la_br, la_switch, la_indirectbr,
  434. la_invoke, la_resume,
  435. la_unreachable,
  436. la_store,
  437. la_fence,
  438. la_cmpxchg,
  439. la_atomicrmw:
  440. begin
  441. { instructions that never have a result }
  442. end;
  443. la_call:
  444. begin
  445. if taillvm(hp).oper[1]^.reg<>NR_NO then
  446. owner.writer.AsmWrite(getregisterstring(taillvm(hp).oper[1]^.reg)+' = ');
  447. opstart:=2;
  448. if llvmflag_call_no_ptr in llvmversion_properties[current_settings.llvmversion] then
  449. begin
  450. owner.writer.AsmWrite(llvm_op2str[op]);
  451. opdone:=true;
  452. tmpstr:=llvmencodetypename(taillvm(hp).oper[2]^.def);
  453. if tmpstr[length(tmpstr)]<>'*' then
  454. begin
  455. writeln(tmpstr);
  456. internalerror(2016071102);
  457. end
  458. else
  459. setlength(tmpstr,length(tmpstr)-1);
  460. owner.writer.AsmWrite(tmpstr);
  461. opstart:=3;
  462. end;
  463. end;
  464. la_blockaddress:
  465. begin
  466. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[0]^,false));
  467. owner.writer.AsmWrite(' = blockaddress(');
  468. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[1]^,false));
  469. owner.writer.AsmWrite(',');
  470. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[2]^,false));
  471. owner.writer.AsmWrite(')');
  472. done:=true;
  473. end;
  474. la_alloca:
  475. begin
  476. owner.writer.AsmWrite(getreferencestring(taillvm(hp).oper[0]^.ref^,false)+' = ');
  477. sep:=' ';
  478. opstart:=1;
  479. end;
  480. la_trunc, la_zext, la_sext, la_fptrunc, la_fpext,
  481. la_fptoui, la_fptosi, la_uitofp, la_sitofp,
  482. la_ptrtoint, la_inttoptr,
  483. la_bitcast:
  484. begin
  485. { destination can be empty in case of nested constructs, or
  486. data initialisers }
  487. if (taillvm(hp).oper[0]^.typ<>top_reg) or
  488. (taillvm(hp).oper[0]^.reg<>NR_NO) then
  489. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[0]^,false)+' = ')
  490. else
  491. nested:=true;
  492. owner.writer.AsmWrite(llvm_op2str[op]);
  493. if not nested then
  494. owner.writer.AsmWrite(' ')
  495. else
  496. owner.writer.AsmWrite(' (');
  497. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[1]^,false));
  498. { if there's a tai operand, its def is used instead of an
  499. explicit def operand }
  500. if taillvm(hp).ops=4 then
  501. begin
  502. owner.writer.AsmWrite(' ');
  503. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[2]^,false));
  504. opstart:=3;
  505. end
  506. else
  507. opstart:=2;
  508. owner.writer.AsmWrite(' to ');
  509. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[opstart]^,false));
  510. done:=true;
  511. end
  512. else
  513. begin
  514. if (taillvm(hp).oper[0]^.typ<>top_reg) or
  515. (taillvm(hp).oper[0]^.reg<>NR_NO) then
  516. begin
  517. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[0]^,true)+' = ');
  518. end
  519. else
  520. nested:=true;
  521. sep:=' ';
  522. opstart:=1
  523. end;
  524. end;
  525. { process operands }
  526. if not done then
  527. begin
  528. if not opdone then
  529. begin
  530. owner.writer.AsmWrite(llvm_op2str[op]);
  531. if nested then
  532. owner.writer.AsmWrite(' (');
  533. end;
  534. if taillvm(hp).ops<>0 then
  535. begin
  536. for i:=opstart to taillvm(hp).ops-1 do
  537. begin
  538. owner.writer.AsmWrite(sep);
  539. owner.writer.AsmWrite(getopstr(taillvm(hp).oper[i]^,op in [la_load,la_store]));
  540. if (taillvm(hp).oper[i]^.typ in [top_def,top_cond,top_fpcond]) or
  541. (op=la_call) then
  542. sep :=' '
  543. else
  544. sep:=', ';
  545. end;
  546. end;
  547. end;
  548. if op=la_alloca then
  549. owner.writer.AsmWrite(getreferencealignstring(taillvm(hp).oper[0]^.ref^));
  550. if nested then
  551. owner.writer.AsmWrite(')')
  552. else if owner.fdecllevel=0 then
  553. owner.writer.AsmLn;
  554. end;
  555. {****************************************************************************}
  556. { LLVM Assembler writer }
  557. {****************************************************************************}
  558. destructor TLLVMAssember.Destroy;
  559. begin
  560. InstrWriter.free;
  561. inherited destroy;
  562. end;
  563. function TLLVMAssember.MakeCmdLine: TCmdStr;
  564. var
  565. optstr: TCmdStr;
  566. begin
  567. result := inherited MakeCmdLine;
  568. { standard optimization flags for llc -- todo: this needs to be split
  569. into a call to opt and one to llc }
  570. if cs_opt_level3 in current_settings.optimizerswitches then
  571. optstr:='-O3'
  572. else if cs_opt_level2 in current_settings.optimizerswitches then
  573. optstr:='-O2'
  574. else if cs_opt_level1 in current_settings.optimizerswitches then
  575. optstr:='-O1'
  576. else
  577. optstr:='-O0';
  578. { stack frame elimination }
  579. if not(cs_opt_stackframe in current_settings.optimizerswitches) then
  580. optstr:=optstr+' -disable-fp-elim';
  581. { fast math }
  582. if cs_opt_fastmath in current_settings.optimizerswitches then
  583. optstr:=optstr+' -enable-unsafe-fp-math -enable-fp-mad -fp-contract=fast';
  584. { smart linking }
  585. if cs_create_smart in current_settings.moduleswitches then
  586. optstr:=optstr+' -fdata-sections -fcode-sections';
  587. { pic }
  588. if cs_create_pic in current_settings.moduleswitches then
  589. optstr:=optstr+' -relocation-model=pic'
  590. else if not(target_info.system in systems_darwin) then
  591. optstr:=optstr+' -relocation-model=static'
  592. else
  593. optstr:=optstr+' -relocation-model=dynamic-no-pic';
  594. { our stack alignment is non-standard on some targets. The following
  595. parameter is however ignored on some targets by llvm, so it may not
  596. be enough }
  597. optstr:=optstr+' -stack-alignment='+tostr(target_info.stackalign*8);
  598. { force object output instead of textual assembler code }
  599. optstr:=optstr+' -filetype=obj';
  600. replace(result,'$OPT',optstr);
  601. end;
  602. procedure TLLVMAssember.WriteTree(p:TAsmList);
  603. var
  604. hp : tai;
  605. InlineLevel : cardinal;
  606. asmblock: boolean;
  607. do_line : boolean;
  608. replaceforbidden: boolean;
  609. begin
  610. if not assigned(p) then
  611. exit;
  612. replaceforbidden:=asminfo^.dollarsign<>'$';
  613. InlineLevel:=0;
  614. asmblock:=false;
  615. { lineinfo is only needed for al_procedures (PFV) }
  616. do_line:=(cs_asm_source in current_settings.globalswitches) or
  617. ((cs_lineinfo in current_settings.moduleswitches)
  618. and (p=current_asmdata.asmlists[al_procedures]));
  619. hp:=tai(p.first);
  620. while assigned(hp) do
  621. begin
  622. prefetch(pointer(hp.next)^);
  623. if not(hp.typ in SkipLineInfo) then
  624. begin
  625. current_filepos:=tailineinfo(hp).fileinfo;
  626. { no line info for inlined code }
  627. if do_line and (inlinelevel=0) then
  628. WriteSourceLine(hp as tailineinfo);
  629. end;
  630. WriteTai(replaceforbidden, do_line, InlineLevel, asmblock, hp);
  631. hp:=tai(hp.next);
  632. end;
  633. end;
  634. procedure TLLVMAssember.WriteExtraHeader;
  635. begin
  636. writer.AsmWrite('target datalayout = "');
  637. writer.AsmWrite(target_info.llvmdatalayout);
  638. writer.AsmWriteln('"');
  639. writer.AsmWrite('target triple = "');
  640. writer.AsmWrite(llvm_target_name);
  641. writer.AsmWriteln('"');
  642. end;
  643. procedure TLLVMAssember.WriteExtraFooter;
  644. begin
  645. end;
  646. procedure TLLVMAssember.WriteInstruction(hp: tai);
  647. begin
  648. end;
  649. procedure TLLVMAssember.WriteLlvmInstruction(hp: tai);
  650. begin
  651. InstrWriter.WriteInstruction(hp);
  652. end;
  653. procedure TLLVMAssember.WriteRealConst(hp: tai_realconst; do_line: boolean);
  654. begin
  655. if do_line and
  656. (fdecllevel=0) then
  657. begin
  658. case tai_realconst(hp).realtyp of
  659. aitrealconst_s32bit:
  660. writer.AsmWriteLn(asminfo^.comment+'value: '+single2str(tai_realconst(hp).value.s32val));
  661. aitrealconst_s64bit:
  662. writer.AsmWriteLn(asminfo^.comment+'value: '+double2str(tai_realconst(hp).value.s64val));
  663. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  664. { can't write full 80 bit floating point constants yet on non-x86 }
  665. aitrealconst_s80bit:
  666. writer.AsmWriteLn(asminfo^.comment+'value: '+extended2str(tai_realconst(hp).value.s80val));
  667. {$endif cpuextended}
  668. aitrealconst_s64comp:
  669. writer.AsmWriteLn(asminfo^.comment+'value: '+extended2str(tai_realconst(hp).value.s64compval));
  670. else
  671. internalerror(2014050604);
  672. end;
  673. end;
  674. case hp.realtyp of
  675. aitrealconst_s32bit:
  676. writer.AsmWriteln(llvmdoubletostr(hp.value.s32val));
  677. aitrealconst_s64bit:
  678. writer.AsmWriteln(llvmdoubletostr(hp.value.s64val));
  679. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  680. aitrealconst_s80bit:
  681. writer.AsmWriteln(llvmextendedtostr(hp.value.s80val));
  682. {$endif defined(cpuextended)}
  683. aitrealconst_s64comp:
  684. { handled as int64 most of the time in llvm }
  685. writer.AsmWriteln(tostr(round(hp.value.s64compval)));
  686. else
  687. internalerror(2014062401);
  688. end;
  689. end;
  690. procedure TLLVMAssember.WriteOrdConst(hp: tai_const);
  691. var
  692. consttyp: taiconst_type;
  693. begin
  694. if fdecllevel=0 then
  695. writer.AsmWrite(asminfo^.comment+' const ');
  696. consttyp:=hp.consttype;
  697. case consttyp of
  698. aitconst_got,
  699. aitconst_gotoff_symbol,
  700. aitconst_uleb128bit,
  701. aitconst_sleb128bit,
  702. aitconst_rva_symbol,
  703. aitconst_secrel32_symbol,
  704. aitconst_darwin_dwarf_delta32,
  705. aitconst_darwin_dwarf_delta64,
  706. aitconst_half16bit,
  707. aitconst_gs:
  708. internalerror(2014052901);
  709. aitconst_128bit,
  710. aitconst_64bit,
  711. aitconst_32bit,
  712. aitconst_16bit,
  713. aitconst_8bit,
  714. aitconst_16bit_unaligned,
  715. aitconst_32bit_unaligned,
  716. aitconst_64bit_unaligned:
  717. begin
  718. if fdecllevel=0 then
  719. writer.AsmWrite(asminfo^.comment);
  720. { can't have compile-time differences between symbols; these are
  721. normally for PIC, but llvm takes care of that for us }
  722. if assigned(hp.endsym) then
  723. internalerror(2014052902);
  724. if assigned(hp.sym) then
  725. begin
  726. writer.AsmWrite(LlvmAsmSymName(hp.sym));
  727. { can't have offsets }
  728. if hp.value<>0 then
  729. if fdecllevel<>0 then
  730. internalerror(2014052903)
  731. else
  732. writer.AsmWrite(' -- symbol offset: ' + tostr(hp.value));
  733. end
  734. else if hp.value=0 then
  735. writer.AsmWrite('zeroinitializer')
  736. else
  737. writer.AsmWrite(tostr(hp.value));
  738. if fdecllevel=0 then
  739. writer.AsmLn;
  740. end;
  741. else
  742. internalerror(200704251);
  743. end;
  744. end;
  745. procedure TLLVMAssember.WriteTai(const replaceforbidden: boolean; const do_line: boolean; var InlineLevel: cardinal; var asmblock: boolean; var hp: tai);
  746. procedure WriteLinkageVibilityFlags(bind: TAsmSymBind);
  747. begin
  748. case bind of
  749. AB_EXTERNAL,
  750. AB_EXTERNAL_INDIRECT:
  751. writer.AsmWrite(' external');
  752. AB_COMMON:
  753. writer.AsmWrite(' common');
  754. AB_LOCAL:
  755. writer.AsmWrite(' internal');
  756. AB_GLOBAL,
  757. AB_INDIRECT:
  758. writer.AsmWrite('');
  759. AB_WEAK_EXTERNAL:
  760. writer.AsmWrite(' extern_weak');
  761. AB_PRIVATE_EXTERN:
  762. begin
  763. if not(llvmflag_linker_private in llvmversion_properties[current_settings.llvmversion]) then
  764. writer.AsmWrite(' hidden')
  765. else
  766. writer.AsmWrite(' linker_private');
  767. end
  768. else
  769. internalerror(2014020104);
  770. end;
  771. end;
  772. procedure WriteFunctionFlags(pd: tprocdef);
  773. begin
  774. if (pos('FPC_SETJMP',upper(pd.mangledname))<>0) or
  775. (pd.mangledname=(target_info.cprefix+'setjmp')) then
  776. writer.AsmWrite(' returns_twice');
  777. if po_inline in pd.procoptions then
  778. writer.AsmWrite(' inlinehint');
  779. { ensure that functions that happen to have the same name as a
  780. standard C library function, but which are implemented in Pascal,
  781. are not considered to have the same semantics as the C function with
  782. the same name }
  783. if not(po_external in pd.procoptions) then
  784. writer.AsmWrite(' nobuiltin');
  785. if po_noreturn in pd.procoptions then
  786. writer.AsmWrite(' noreturn');
  787. end;
  788. procedure WriteTypedConstData(hp: tai_abstracttypedconst);
  789. var
  790. p: tai_abstracttypedconst;
  791. pval: tai;
  792. defstr: TSymStr;
  793. first, gotstring: boolean;
  794. begin
  795. defstr:=llvmencodetypename(hp.def);
  796. { write the struct, array or simple type }
  797. case hp.adetyp of
  798. tck_record:
  799. begin
  800. writer.AsmWrite(defstr);
  801. writer.AsmWrite(' <{');
  802. first:=true;
  803. for p in tai_aggregatetypedconst(hp) do
  804. begin
  805. if not first then
  806. writer.AsmWrite(', ')
  807. else
  808. first:=false;
  809. WriteTypedConstData(p);
  810. end;
  811. writer.AsmWrite('}>');
  812. end;
  813. tck_array:
  814. begin
  815. writer.AsmWrite(defstr);
  816. first:=true;
  817. gotstring:=false;
  818. for p in tai_aggregatetypedconst(hp) do
  819. begin
  820. if not first then
  821. writer.AsmWrite(',')
  822. else
  823. begin
  824. writer.AsmWrite(' ');
  825. if (tai_abstracttypedconst(p).adetyp=tck_simple) and
  826. (tai_simpletypedconst(p).val.typ=ait_string) then
  827. begin
  828. gotstring:=true;
  829. end
  830. else
  831. begin
  832. writer.AsmWrite('[');
  833. end;
  834. first:=false;
  835. end;
  836. { cannot concat strings and other things }
  837. if gotstring and
  838. ((tai_abstracttypedconst(p).adetyp<>tck_simple) or
  839. (tai_simpletypedconst(p).val.typ<>ait_string)) then
  840. internalerror(2014062701);
  841. WriteTypedConstData(p);
  842. end;
  843. if not gotstring then
  844. writer.AsmWrite(']');
  845. end;
  846. tck_simple:
  847. begin
  848. pval:=tai_simpletypedconst(hp).val;
  849. if pval.typ<>ait_string then
  850. begin
  851. writer.AsmWrite(defstr);
  852. writer.AsmWrite(' ');
  853. end;
  854. WriteTai(replaceforbidden,do_line,InlineLevel,asmblock,pval);
  855. end;
  856. end;
  857. end;
  858. var
  859. hp2: tai;
  860. s: string;
  861. i: longint;
  862. ch: ansichar;
  863. begin
  864. case hp.typ of
  865. ait_comment :
  866. begin
  867. writer.AsmWrite(asminfo^.comment);
  868. writer.AsmWritePChar(tai_comment(hp).str);
  869. if fdecllevel<>0 then
  870. internalerror(2015090601);
  871. writer.AsmLn;
  872. end;
  873. ait_regalloc :
  874. begin
  875. if (cs_asm_regalloc in current_settings.globalswitches) then
  876. begin
  877. writer.AsmWrite(#9+asminfo^.comment+'Register ');
  878. repeat
  879. writer.AsmWrite(std_regname(Tai_regalloc(hp).reg));
  880. if (hp.next=nil) or
  881. (tai(hp.next).typ<>ait_regalloc) or
  882. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  883. break;
  884. hp:=tai(hp.next);
  885. writer.AsmWrite(',');
  886. until false;
  887. writer.AsmWrite(' ');
  888. writer.AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  889. end;
  890. end;
  891. ait_tempalloc :
  892. begin
  893. if (cs_asm_tempalloc in current_settings.globalswitches) then
  894. WriteTempalloc(tai_tempalloc(hp));
  895. end;
  896. ait_align,
  897. ait_section :
  898. begin
  899. { ignore, specified as part of declarations -- don't write
  900. comment, because could appear in the middle of an aggregate
  901. constant definition }
  902. end;
  903. ait_datablock :
  904. begin
  905. writer.AsmWrite(asminfo^.comment);
  906. writer.AsmWriteln('datablock');
  907. end;
  908. ait_const:
  909. begin
  910. WriteOrdConst(tai_const(hp));
  911. end;
  912. ait_realconst :
  913. begin
  914. WriteRealConst(tai_realconst(hp), do_line);
  915. end;
  916. ait_string :
  917. begin
  918. if fdecllevel=0 then
  919. writer.AsmWrite(asminfo^.comment);
  920. writer.AsmWrite('c"');
  921. for i:=1 to tai_string(hp).len do
  922. begin
  923. ch:=tai_string(hp).str[i-1];
  924. case ch of
  925. #0, {This can't be done by range, because a bug in FPC}
  926. #1..#31,
  927. #128..#255,
  928. '"',
  929. '\' : s:='\'+hexStr(ord(ch),2);
  930. else
  931. s:=ch;
  932. end;
  933. writer.AsmWrite(s);
  934. end;
  935. writer.AsmWriteLn('"');
  936. end;
  937. ait_label :
  938. begin
  939. if not asmblock and
  940. (tai_label(hp).labsym.is_used) then
  941. begin
  942. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  943. begin
  944. { should be emitted as part of the variable/function def }
  945. internalerror(2013010703);
  946. end;
  947. if tai_label(hp).labsym.bind in [AB_GLOBAL, AB_PRIVATE_EXTERN] then
  948. begin
  949. { should be emitted as part of the variable/function def }
  950. //internalerror(2013010704);
  951. writer.AsmWriteln(asminfo^.comment+'global/privateextern label: '+tai_label(hp).labsym.name);
  952. end;
  953. if replaceforbidden then
  954. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  955. else
  956. writer.AsmWrite(tai_label(hp).labsym.name);
  957. writer.AsmWriteLn(':');
  958. end;
  959. end;
  960. ait_symbol :
  961. begin
  962. if fdecllevel=0 then
  963. writer.AsmWrite(asminfo^.comment);
  964. writer.AsmWriteln(LlvmAsmSymName(tai_symbol(hp).sym));
  965. { todo }
  966. if tai_symbol(hp).has_value then
  967. internalerror(2014062402);
  968. end;
  969. ait_llvmdecl:
  970. begin
  971. if taillvmdecl(hp).def.typ=procdef then
  972. begin
  973. if not(ldf_definition in taillvmdecl(hp).flags) then
  974. begin
  975. writer.AsmWrite('declare');
  976. writer.AsmWrite(llvmencodeproctype(tprocdef(taillvmdecl(hp).def), taillvmdecl(hp).namesym.name, lpd_decl));
  977. WriteFunctionFlags(tprocdef(taillvmdecl(hp).def));
  978. writer.AsmLn;
  979. end
  980. else
  981. begin
  982. writer.AsmWrite('define');
  983. if ldf_weak in taillvmdecl(hp).flags then
  984. writer.AsmWrite(' weak');
  985. WriteLinkageVibilityFlags(taillvmdecl(hp).namesym.bind);
  986. writer.AsmWrite(llvmencodeproctype(tprocdef(taillvmdecl(hp).def), '', lpd_def));
  987. WriteFunctionFlags(tprocdef(taillvmdecl(hp).def));
  988. writer.AsmWriteln(' {');
  989. end;
  990. end
  991. else
  992. begin
  993. writer.AsmWrite(LlvmAsmSymName(taillvmdecl(hp).namesym));
  994. writer.AsmWrite(' =');
  995. if ldf_weak in taillvmdecl(hp).flags then
  996. writer.AsmWrite(' weak');
  997. WriteLinkageVibilityFlags(taillvmdecl(hp).namesym.bind);
  998. writer.AsmWrite(' ');
  999. if (ldf_tls in taillvmdecl(hp).flags) then
  1000. writer.AsmWrite('thread_local ');
  1001. if ldf_unnamed_addr in taillvmdecl(hp).flags then
  1002. writer.AsmWrite('unnamed_addr ');
  1003. if taillvmdecl(hp).sec in [sec_rodata,sec_rodata_norel] then
  1004. writer.AsmWrite('constant ')
  1005. else
  1006. writer.AsmWrite('global ');
  1007. if not assigned(taillvmdecl(hp).initdata) then
  1008. begin
  1009. writer.AsmWrite(llvmencodetypename(taillvmdecl(hp).def));
  1010. if not(taillvmdecl(hp).namesym.bind in [AB_EXTERNAL, AB_WEAK_EXTERNAL,AB_EXTERNAL_INDIRECT]) then
  1011. writer.AsmWrite(' zeroinitializer');
  1012. end
  1013. else
  1014. begin
  1015. inc(fdecllevel);
  1016. { can't have an external symbol with initialisation data }
  1017. if taillvmdecl(hp).namesym.bind in [AB_EXTERNAL, AB_WEAK_EXTERNAL] then
  1018. internalerror(2014052905);
  1019. { bitcast initialisation data to the type of the constant }
  1020. { write initialisation data }
  1021. hp2:=tai(taillvmdecl(hp).initdata.first);
  1022. while assigned(hp2) do
  1023. begin
  1024. WriteTai(replaceforbidden,do_line,InlineLevel,asmblock,hp2);
  1025. hp2:=tai(hp2.next);
  1026. end;
  1027. dec(fdecllevel);
  1028. end;
  1029. { custom section name? }
  1030. case taillvmdecl(hp).sec of
  1031. sec_user:
  1032. begin
  1033. writer.AsmWrite(', section "');
  1034. writer.AsmWrite(taillvmdecl(hp).secname);
  1035. writer.AsmWrite('"');
  1036. end;
  1037. low(TObjCAsmSectionType)..high(TObjCAsmSectionType):
  1038. begin
  1039. writer.AsmWrite(', section "');
  1040. writer.AsmWrite(objc_section_name(taillvmdecl(hp).sec));
  1041. writer.AsmWrite('"');
  1042. end;
  1043. end;
  1044. { alignment }
  1045. writer.AsmWrite(', align ');
  1046. writer.AsmWriteln(tostr(taillvmdecl(hp).alignment));
  1047. end;
  1048. end;
  1049. ait_llvmalias:
  1050. begin
  1051. writer.AsmWrite(LlvmAsmSymName(taillvmalias(hp).newsym));
  1052. writer.AsmWrite(' = alias ');
  1053. WriteLinkageVibilityFlags(taillvmalias(hp).bind);
  1054. if taillvmalias(hp).def.typ=procdef then
  1055. writer.AsmWrite(llvmencodeproctype(tabstractprocdef(taillvmalias(hp).def), '', lpd_alias))
  1056. else
  1057. writer.AsmWrite(llvmencodetypename(taillvmalias(hp).def));
  1058. writer.AsmWrite('* ');
  1059. writer.AsmWriteln(LlvmAsmSymName(taillvmalias(hp).oldsym));
  1060. end;
  1061. ait_symbolpair:
  1062. begin
  1063. { should be emitted as part of the symbol def }
  1064. internalerror(2013010708);
  1065. end;
  1066. ait_symbol_end :
  1067. begin
  1068. if tai_symbol_end(hp).sym.typ=AT_FUNCTION then
  1069. writer.AsmWriteln('}')
  1070. else
  1071. writer.AsmWriteln('; ait_symbol_end error, should not be generated');
  1072. // internalerror(2013010711);
  1073. end;
  1074. ait_instruction :
  1075. begin
  1076. WriteInstruction(hp);
  1077. end;
  1078. ait_llvmins:
  1079. begin
  1080. WriteLlvmInstruction(hp);
  1081. end;
  1082. ait_stab :
  1083. begin
  1084. internalerror(2013010712);
  1085. end;
  1086. ait_force_line,
  1087. ait_function_name :
  1088. ;
  1089. ait_cutobject :
  1090. begin
  1091. end;
  1092. ait_marker :
  1093. case
  1094. tai_marker(hp).kind of
  1095. mark_NoLineInfoStart:
  1096. inc(InlineLevel);
  1097. mark_NoLineInfoEnd:
  1098. dec(InlineLevel);
  1099. { these cannot be nested }
  1100. mark_AsmBlockStart:
  1101. asmblock:=true;
  1102. mark_AsmBlockEnd:
  1103. asmblock:=false;
  1104. end;
  1105. ait_directive :
  1106. begin
  1107. { CPU directive is commented out for the LLVM }
  1108. if tai_directive(hp).directive=asd_cpu then
  1109. writer.AsmWrite(asminfo^.comment);
  1110. WriteDirectiveName(tai_directive(hp).directive);
  1111. if tai_directive(hp).name <>'' then
  1112. writer.AsmWrite(tai_directive(hp).name);
  1113. if fdecllevel<>0 then
  1114. internalerror(2015090602);
  1115. writer.AsmLn;
  1116. end;
  1117. ait_seh_directive :
  1118. begin
  1119. internalerror(2013010713);
  1120. end;
  1121. ait_varloc:
  1122. begin
  1123. if tai_varloc(hp).newlocationhi<>NR_NO then
  1124. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1125. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation)))
  1126. else
  1127. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1128. std_regname(tai_varloc(hp).newlocation)));
  1129. if fdecllevel<>0 then
  1130. internalerror(2015090603);
  1131. writer.AsmLn;
  1132. end;
  1133. ait_typedconst:
  1134. begin
  1135. WriteTypedConstData(tai_abstracttypedconst(hp));
  1136. end
  1137. else
  1138. internalerror(2006012201);
  1139. end;
  1140. end;
  1141. constructor TLLVMAssember.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
  1142. begin
  1143. inherited;
  1144. InstrWriter:=TLLVMInstrWriter.create(self);
  1145. end;
  1146. procedure TLLVMAssember.WriteDirectiveName(dir: TAsmDirective);
  1147. begin
  1148. writer.AsmWrite('.'+directivestr[dir]+' ');
  1149. end;
  1150. procedure TLLVMAssember.WriteAsmList;
  1151. var
  1152. hal : tasmlisttype;
  1153. i: longint;
  1154. a: TExternalAssembler;
  1155. decorator: TLLVMModuleInlineAssemblyDecorator;
  1156. begin
  1157. WriteExtraHeader;
  1158. for hal:=low(TasmlistType) to high(TasmlistType) do
  1159. begin
  1160. if not assigned(current_asmdata.asmlists[hal]) or
  1161. current_asmdata.asmlists[hal].Empty then
  1162. continue;
  1163. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1164. if hal<>al_pure_assembler then
  1165. writetree(current_asmdata.asmlists[hal])
  1166. else
  1167. begin
  1168. { write routines using the target-specific external assembler
  1169. writer, filtered using the LLVM module-level assembly
  1170. decorator }
  1171. decorator:=TLLVMModuleInlineAssemblyDecorator.Create;
  1172. writer.decorator:=decorator;
  1173. a:=GetExternalGnuAssemblerWithAsmInfoWriter(asminfo,writer);
  1174. a.WriteTree(current_asmdata.asmlists[hal]);
  1175. writer.decorator:=nil;
  1176. decorator.free;
  1177. a.free;
  1178. end;
  1179. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1180. end;
  1181. writer.AsmLn;
  1182. end;
  1183. {****************************************************************************}
  1184. { Abstract Instruction Writer }
  1185. {****************************************************************************}
  1186. constructor TLLVMInstrWriter.create(_owner: TLLVMAssember);
  1187. begin
  1188. inherited create;
  1189. owner := _owner;
  1190. end;
  1191. const
  1192. as_llvm_info : tasminfo =
  1193. (
  1194. id : as_llvm;
  1195. idtxt : 'LLVM-AS';
  1196. asmbin : 'llc';
  1197. asmcmd: '$OPT -o $OBJ $ASM';
  1198. supported_targets : [system_x86_64_linux,system_x86_64_darwin,system_powerpc64_darwin];
  1199. flags : [af_smartlink_sections];
  1200. labelprefix : 'L';
  1201. comment : '; ';
  1202. dollarsign: '$';
  1203. );
  1204. begin
  1205. RegisterAssembler(as_llvm_info,TLLVMAssember);
  1206. end.