agllvm.pas 47 KB

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