agllvm.pas 50 KB

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