1 { 2 Copyright (c) 2010, 2013 by Jonas Maebe 3 4 Contains the assembler object for the LLVM target 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 **************************************************************************** 21 } 22 unit aasmllvm; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 globtype,verbose,cclasses, 30 aasmbase,aasmtai,aasmdata,aasmsym, 31 cpubase,cgbase,cgutils, 32 symtype,symdef,symsym, 33 llvmbase; 34 35 type 36 { taillvm } 37 taillvm = class(tai_cpu_abstract_sym) 38 llvmopcode: tllvmop; 39 40 constructor create_llvm(op: tllvmop); 41 42 { e.g. ret void } 43 constructor op_size(op : tllvmop; size: tdef); 44 45 { e.g. dst = alloca size } 46 constructor op_reg_size(op:tllvmop;dst:tregister;size:tdef); 47 { e.g. dst = alloca size } 48 constructor op_ref_size(op:tllvmop;const dst:treference;size:tdef); 49 50 { e.g. dst = add size src1, src2 } 51 constructor op_reg_size_reg_reg(op:tllvmop;dst:tregister;size:tdef;src1,src2:tregister); 52 { e.g. dst = shl size src1, 1 ( = src1 shl 1) } 53 constructor op_reg_size_reg_const(op:tllvmop;dst:tregister;size:tdef;src1:tregister;src2:int64); 54 { e.g. dst = sub size 0, src2 ( = 0 - src2) } 55 constructor op_reg_size_const_reg(op:tllvmop;dst:tregister;size:tdef;src1:int64;src2:tregister); 56 { e.g. dst = bitcast size1 src to tosize } 57 constructor op_reg_size_reg_size(op:tllvmop;dst:tregister;fromsize:tdef;src:tregister;tosize:tdef); 58 { e.g. dst = bitcast fromsize 255 to tosize } 59 constructor op_reg_size_const_size(op:tllvmop;dst:tregister;fromsize:tdef;src:int64;tosize:tdef); 60 { e.g. dst = bitcast fromsize double to tosize } 61 constructor op_reg_size_fpconst_size(op:tllvmop;dst:tregister;fromsize:tdef;src:double;tosize:tdef); 62 {$ifdef cpuextended} 63 { e.g. dst = bitcast fromsize extended to tosize } 64 constructor op_reg_size_fpconst80_size(op:tllvmop;dst:tregister;fromsize:tdef;src:extended;tosize:tdef); 65 {$endif cpuextended} 66 { e.g. dst = bitcast fromsize @globalvar to tosize } 67 constructor op_reg_size_sym_size(op:tllvmop;dst:tregister;fromsize:tdef;src:TAsmSymbol;tosize:tdef); 68 { e.g. dst = bitcast fromsize <abstracttaidata> to tosize } 69 constructor op_reg_tai_size(op:tllvmop;dst:tregister;src:tai;tosize:tdef); 70 71 { dst = bitcast size undef to size } 72 constructor op_reg_size_undef(op: tllvmop; dst: tregister; size: tdef); 73 74 { return size undef } 75 constructor op_size_undef(op: tllvmop; size: tdef); 76 77 { e.g. dst = bitcast fromsize src to tosize } 78 constructor op_reg_size_ref_size(op:tllvmop;dst:tregister;fromsize:tdef;const src:treference;tosize:tdef); 79 { e.g. store fromsize src, ptrsize toref} 80 constructor op_size_reg_size_ref(op:tllvmop;fromsize:tdef;src:tregister;ptrsize:tdef;const toref:treference); 81 { e.g. store fromsize srcref, ptrsize toref (with srcref.refaddr=full) } 82 constructor op_size_ref_size_ref(op:tllvmop;fromsize:tdef;const src:treference;ptrsize:tdef;const toref:treference); 83 { e.g. store fromsize const, ptrsize toref} 84 constructor op_size_const_size_ref(op:tllvmop;fromsize:tdef;src:int64;ptrsize:tdef;const toref:treference); 85 { e.g. dst = load fromsize fromref } 86 constructor op_reg_size_ref(op:tllvmop;dst:tregister;fromsize:tdef;const fromref:treference); 87 88 { e.g. dst = icmp cmpcond size reg1, reg2 } 89 constructor op_reg_cond_size_reg_reg(op:tllvmop;dst:tregister;cmpcond:topcmp;size:tdef;reg1,reg2:tregister); 90 { e.g. dst = icmp cmpcond size reg1, constant } 91 constructor op_reg_cond_size_reg_const(op:tllvmop;dst:tregister;cmpcond:topcmp;size:tdef;reg1:tregister;cnst:int64); 92 { e.g. dst = fcmp cmpcond size reg1, reg2 } 93 constructor op_reg_fpcond_size_reg_reg(op:tllvmop;dst:tregister;cmpcond:tllvmfpcmp;size:tdef;reg1,reg2:tregister); 94 { e.g. br label lab } 95 constructor op_lab(op:tllvmop;lab:tasmlabel); 96 { e.g. br i1 condreg, label iftrue, label iffalse } 97 constructor op_size_reg_lab_lab(op:tllvmop;fromsize:tdef;condreg:tregister;labtrue,labfalse: tasmlabel); 98 99 { e.g. la_ret retdef retval } 100 constructor op_size_reg(op:tllvmop;def: tdef;reg: tregister); 101 102 { e.g. dst = getelementptr ptrsize ref, i32 0 (if indirect), index1type index1 } 103 constructor getelementptr_reg_size_ref_size_reg(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:tregister;indirect:boolean); 104 constructor getelementptr_reg_size_ref_size_const(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:ptrint;indirect:boolean); 105 constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:tai;indextype:tdef;index1:ptrint;indirect:boolean); 106 107 constructor blockaddress(fun, lab: tasmsymbol); 108 constructor landingpad(dst:tregister;def:tdef;firstclause:taillvm); 109 constructor exceptclause(op:tllvmop;def:tdef;kind:TAsmSymbol;nextclause:taillvm); 110 111 { e.g. dst = call retsize name (paras) } 112 constructor call_size_name_paras(callpd: tdef; dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist); 113 { e.g. dst = call retsize reg (paras) } 114 constructor call_size_reg_paras(callpd: tdef; dst: tregister;retsize: tdef;reg:tregister;paras: tfplist); 115 116 { inline function-level assembler code and parameters } 117 constructor asm_paras(asmlist: tasmlist; paras: tfplist); 118 119 procedure loadoper(opidx: longint; o: toper); override; 120 procedure clearop(opidx: longint); override; 121 procedure loadtai(opidx: longint; _ai: tai); 122 procedure loaddef(opidx: longint; _def: tdef); 123 procedure loadundef(opidx: longint); 124 procedure loadsingle(opidx: longint; _sval: single); 125 procedure loaddouble(opidx: longint; _dval: double); 126 {$ifdef cpuextended} 127 procedure loadextended(opidx: longint; _eval: extended); 128 {$endif cpuextended} 129 procedure loadcond(opidx: longint; _cond: topcmp); 130 procedure loadfpcond(opidx: longint; _fpcond: tllvmfpcmp); 131 procedure loadparas(opidx: longint; _paras: tfplist); 132 procedure loadasmlist(opidx: longint; _asmlist: tasmlist); 133 134 { register spilling code } spilling_get_operation_typenull135 function spilling_get_operation_type(opnr: longint): topertype;override; spilling_get_reg_typenull136 function spilling_get_reg_type(opnr: longint): tdef; 137 end; 138 139 140 tllvmvisibility = (llv_default, llv_hidden, llv_protected); 141 142 tllvmlinkage = ( 143 { llvm 2.5 } 144 lll_default { = externally visible/global }, 145 lll_private, lll_internal, lll_linkonce, lll_common, 146 lll_weak, lll_appending, lll_extern_weak, 147 lll_dllimport, lll_dllexport, 148 { llvm 2.6+ } 149 lll_linker_private, lll_private_weak, lll_private_weak_def_auto, 150 lll_available_externally,lll_linkonce_odr, lll_weak_odr 151 ); 152 153 taillvmalias = class(tailineinfo) 154 bind: tasmsymbind; 155 oldsym, newsym: TAsmSymbol; 156 def: tdef; 157 constructor create(_oldsym: tasmsymbol; const newname: TSymStr; _def: tdef; _bind: tasmsymbind); 158 end; 159 160 taillvmdeclflag = 161 ( 162 ldf_definition, { definition as opposed to (an external) declaration } 163 ldf_tls, { tls definition } 164 ldf_unnamed_addr, { address doesn't matter, only content } 165 ldf_vectorized, { vectorized, dead-strippable data } 166 ldf_weak, { weak definition } 167 ldf_appending { appending linkage definition } 168 ); 169 taillvmdeclflags = set of taillvmdeclflag; 170 171 { declarations/definitions of symbols (procedures, variables), both defined 172 here and external } 173 taillvmdecl = class(tai) 174 { initialisation data, if any } 175 initdata: tasmlist; 176 namesym: tasmsymbol; 177 def: tdef; 178 sec: TAsmSectiontype; 179 alignment: shortint; 180 flags: taillvmdeclflags; 181 secname: TSymStr; 182 constructor createdecl(_namesym: tasmsymbol; _def: tdef; _initdata: tasmlist; _sec: tasmsectiontype; _alignment: shortint); 183 constructor createdef(_namesym: tasmsymbol; _def: tdef; _initdata: tasmlist; _sec: tasmsectiontype; _alignment: shortint); 184 constructor createtls(_namesym: tasmsymbol; _def: tdef; _alignment: shortint); 185 procedure setsecname(const name: TSymStr); 186 destructor destroy; override; 187 end; 188 189 { parameter to an llvm call instruction } 190 pllvmcallpara = ^tllvmcallpara; 191 tllvmcallpara = record 192 def: tdef; 193 valueext: tllvmvalueextension; 194 byval, 195 sret: boolean; 196 case loc: tcgloc of 197 LOC_REFERENCE, 198 LOC_REGISTER, 199 LOC_FPUREGISTER, 200 LOC_MMREGISTER: (reg: tregister); 201 LOC_CONSTANT: (value: tcgint); 202 end; 203 204 205 implementation 206 207 uses 208 cutils, strings, 209 symconst, 210 aasmcnst,aasmcpu; 211 212 { taillvmprocdecl } 213 214 constructor taillvmdecl.createdecl(_namesym: tasmsymbol; _def: tdef; _initdata: tasmlist; _sec: tasmsectiontype; _alignment: shortint); 215 begin 216 inherited create; 217 typ:=ait_llvmdecl; 218 namesym:=_namesym; 219 def:=_def; 220 initdata:=_initdata; 221 sec:=_sec; 222 alignment:=_alignment; 223 _namesym.declared:=true; 224 flags:=[]; 225 end; 226 227 228 constructor taillvmdecl.createdef(_namesym: tasmsymbol; _def: tdef; _initdata: tasmlist; _sec: tasmsectiontype; _alignment: shortint); 229 begin 230 createdecl(_namesym,_def,_initdata,_sec,_alignment); 231 include(flags,ldf_definition); 232 end; 233 234 235 constructor taillvmdecl.createtls(_namesym: tasmsymbol; _def: tdef; _alignment: shortint); 236 begin 237 createdef(_namesym,_def,nil,sec_data,_alignment); 238 include(flags,ldf_tls); 239 end; 240 241 242 procedure taillvmdecl.setsecname(const name: TSymStr); 243 begin 244 if sec<>sec_user then 245 internalerror(2015111501); 246 secname:=name; 247 end; 248 249 250 destructor taillvmdecl.destroy; 251 begin 252 initdata.free; 253 inherited destroy; 254 end; 255 256 { taillvmalias } 257 258 constructor taillvmalias.create(_oldsym: tasmsymbol; const newname: TSymStr; _def: tdef; _bind: tasmsymbind); 259 begin 260 inherited Create; 261 typ:=ait_llvmalias; 262 oldsym:=_oldsym; _defnull263 newsym:=current_asmdata.DefineAsmSymbol(newname,AB_GLOBAL,AT_FUNCTION,_def); 264 newsym.declared:=true; 265 def:=_def; 266 { alias cannot be external } 267 case _bind of 268 { weak external should actually become weak, but we don't support that 269 yet } 270 AB_WEAK_EXTERNAL: 271 internalerror(2016071203); 272 AB_EXTERNAL: 273 _bind:=AB_GLOBAL; 274 AB_EXTERNAL_INDIRECT: 275 _bind:=AB_INDIRECT; 276 end; 277 bind:=_bind; 278 end; 279 280 281 282 283 {***************************************************************************** 284 taicpu Constructors 285 *****************************************************************************} 286 287 constructor taillvm.create_llvm(op: tllvmop); 288 begin 289 create(a_none); 290 llvmopcode:=op; 291 typ:=ait_llvmins; 292 end; 293 294 295 procedure taillvm.loadoper(opidx: longint; o: toper); 296 var 297 i: longint; 298 callpara: pllvmcallpara; 299 begin 300 inherited; 301 if o.typ=top_para then 302 begin 303 oper[opidx]^.paras:=tfplist.create; 304 for i:=0 to o.paras.count-1 do 305 begin 306 new(callpara); 307 callpara^:=pllvmcallpara(o.paras[i])^; 308 oper[opidx]^.paras.add(callpara); 309 if (callpara^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and 310 assigned(add_reg_instruction_hook) then 311 add_reg_instruction_hook(self,callpara^.reg); 312 end; 313 end; 314 end; 315 316 317 procedure taillvm.clearop(opidx: longint); 318 var 319 i: longint; 320 begin 321 case oper[opidx]^.typ of 322 top_para: 323 begin 324 for i:=0 to oper[opidx]^.paras.count-1 do 325 dispose(pllvmcallpara(oper[opidx]^.paras[i])); 326 oper[opidx]^.paras.free; 327 end; 328 top_tai: 329 oper[opidx]^.ai.free; 330 top_asmlist: 331 oper[opidx]^.asmlist.free; 332 end; 333 inherited; 334 end; 335 336 337 procedure taillvm.loadtai(opidx: longint; _ai: tai); 338 begin 339 allocate_oper(opidx+1); 340 with oper[opidx]^ do 341 begin 342 clearop(opidx); 343 ai:=_ai; 344 typ:=top_tai; 345 end; 346 end; 347 348 349 procedure taillvm.loaddef(opidx:longint;_def: tdef); 350 begin 351 allocate_oper(opidx+1); 352 with oper[opidx]^ do 353 begin 354 if typ<>top_def then 355 clearop(opidx); 356 def:=_def; 357 typ:=top_def; 358 end; 359 end; 360 361 362 procedure taillvm.loadundef(opidx: longint); 363 begin 364 allocate_oper(opidx+1); 365 with oper[opidx]^ do 366 typ:=top_undef 367 end; 368 369 370 procedure taillvm.loadsingle(opidx: longint; _sval: single); 371 begin 372 allocate_oper(opidx+1); 373 with oper[opidx]^ do 374 begin 375 if typ<>top_single then 376 clearop(opidx); 377 sval:=_sval; 378 typ:=top_single; 379 end; 380 end; 381 382 383 procedure taillvm.loaddouble(opidx: longint; _dval: double); 384 begin 385 allocate_oper(opidx+1); 386 with oper[opidx]^ do 387 begin 388 if typ<>top_double then 389 clearop(opidx); 390 dval:=_dval; 391 typ:=top_double; 392 end; 393 end; 394 395 396 {$ifdef cpuextended} 397 procedure taillvm.loadextended(opidx: longint; _eval: extended); 398 begin 399 allocate_oper(opidx+1); 400 with oper[opidx]^ do 401 begin 402 if typ<>top_extended80 then 403 clearop(opidx); 404 eval:=_eval; 405 typ:=top_extended80; 406 end; 407 end; 408 {$endif cpuextended} 409 410 411 procedure taillvm.loadcond(opidx: longint; _cond: topcmp); 412 begin 413 allocate_oper(opidx+1); 414 with oper[opidx]^ do 415 begin 416 if typ<>top_cond then 417 clearop(opidx); 418 cond:=_cond; 419 typ:=top_cond; 420 end; 421 end; 422 423 procedure taillvm.loadfpcond(opidx: longint; _fpcond: tllvmfpcmp); 424 begin 425 allocate_oper(opidx+1); 426 with oper[opidx]^ do 427 begin 428 if typ<>top_fpcond then 429 clearop(opidx); 430 fpcond:=_fpcond; 431 typ:=top_fpcond; 432 end; 433 end; 434 435 436 procedure taillvm.loadparas(opidx: longint; _paras: tfplist); 437 var 438 callpara: pllvmcallpara; 439 i: longint; 440 begin 441 allocate_oper(opidx+1); 442 with oper[opidx]^ do 443 begin 444 clearop(opidx); 445 paras:=_paras; 446 for i:=0 to _paras.count-1 do 447 begin 448 callpara:=pllvmcallpara(_paras[i]); 449 if (callpara^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER]) and 450 assigned(add_reg_instruction_hook) then 451 add_reg_instruction_hook(self,callpara^.reg); 452 end; 453 typ:=top_para; 454 end; 455 end; 456 457 458 procedure taillvm.loadasmlist(opidx: longint; _asmlist: tasmlist); 459 begin 460 allocate_oper(opidx+1); 461 with oper[opidx]^ do 462 begin 463 clearop(opidx); 464 asmlist:=_asmlist; 465 typ:=top_asmlist; 466 end; 467 end; 468 469 taillvm.spilling_get_operation_typenull470 function taillvm.spilling_get_operation_type(opnr: longint): topertype; 471 begin 472 case llvmopcode of 473 la_ret, la_br, la_switch, la_indirectbr, 474 la_resume, 475 la_unreachable, 476 la_store, 477 la_fence, 478 la_cmpxchg, 479 la_atomicrmw: 480 begin 481 { instructions that never have a result } 482 result:=operand_read; 483 end; 484 la_alloca, 485 la_trunc, la_zext, la_sext, la_fptrunc, la_fpext, 486 la_fptoui, la_fptosi, la_uitofp, la_sitofp, 487 la_ptrtoint, la_inttoptr, 488 la_bitcast, 489 la_add, la_fadd, la_sub, la_fsub, la_mul, la_fmul, 490 la_udiv,la_sdiv, la_fdiv, la_urem, la_srem, la_frem, 491 la_shl, la_lshr, la_ashr, la_and, la_or, la_xor, 492 la_extractelement, la_insertelement, la_shufflevector, 493 la_extractvalue, la_insertvalue, 494 la_getelementptr, 495 la_load, 496 la_icmp, la_fcmp, 497 la_phi, la_select, 498 la_va_arg, la_landingpad: 499 begin 500 if opnr=0 then 501 result:=operand_write 502 else 503 result:=operand_read; 504 end; 505 la_invoke, la_call: 506 begin 507 if opnr=1 then 508 result:=operand_write 509 else 510 result:=operand_read; 511 end; 512 la_blockaddress: 513 case opnr of 514 0: result:=operand_write 515 else 516 result:=operand_read; 517 end 518 else 519 internalerror(2013103101) 520 end; 521 end; 522 523 taillvm.spilling_get_reg_typenull524 function taillvm.spilling_get_reg_type(opnr: longint): tdef; 525 begin 526 case llvmopcode of 527 la_trunc, la_zext, la_sext, la_fptrunc, la_fpext, 528 la_fptoui, la_fptosi, la_uitofp, la_sitofp, 529 la_ptrtoint, la_inttoptr, 530 la_bitcast: 531 begin 532 { toreg = bitcast fromsize fromreg to tosize } 533 case opnr of 534 0: result:=oper[3]^.def; 535 2: result:=oper[1]^.def 536 else 537 internalerror(2013103102); 538 end; 539 end; 540 la_ret, la_switch, la_indirectbr, 541 la_resume: 542 begin 543 { ret size reg } 544 if opnr=1 then 545 result:=oper[0]^.def 546 else 547 internalerror(2013110101); 548 end; 549 la_invoke, la_call: 550 begin 551 case opnr of 552 1: result:=oper[0]^.def; 553 3: 554 begin 555 if oper[3]^.typ=top_reg then 556 result:=oper[2]^.def 557 else 558 internalerror(2015112001) 559 end 560 else 561 internalerror(2013110102); 562 end; 563 end; 564 la_br, 565 la_unreachable: 566 internalerror(2013110103); 567 la_store: 568 begin 569 case opnr of 570 1: result:=oper[0]^.def; 571 { type of the register in the reference } 572 3: result:=oper[2]^.def; 573 else 574 internalerror(2013110104); 575 end; 576 end; 577 la_load: 578 begin 579 { dst = load ptrdef srcref } 580 case opnr of 581 0: result:=tpointerdef(oper[1]^.def).pointeddef; 582 2: result:=oper[1]^.def; 583 else 584 internalerror(2013110105); 585 end; 586 end; 587 la_getelementptr: 588 begin 589 { dst = getelementptr ref ... } 590 case opnr of 591 0: 592 begin 593 case oper[1]^.typ of 594 top_def: 595 result:=oper[1]^.def; 596 top_tai: 597 begin 598 case oper[1]^.ai.typ of 599 ait_llvmins: 600 result:=taillvm(oper[1]^.ai).spilling_get_reg_type(0); 601 ait_typedconst: 602 result:=tai_abstracttypedconst(oper[1]^.ai).def 603 else 604 internalerror(2016071202); 605 end 606 end 607 else 608 internalerror(2016071201); 609 end 610 end; 611 2: 612 result:=oper[1]^.def; 613 else 614 internalerror(2013110105); 615 end; 616 end; 617 la_fence, 618 la_cmpxchg, 619 la_atomicrmw: 620 begin 621 internalerror(2013110610); 622 end; 623 la_add, la_fadd, la_sub, la_fsub, la_mul, la_fmul, 624 la_udiv,la_sdiv, la_fdiv, la_urem, la_srem, la_frem, 625 la_shl, la_lshr, la_ashr, la_and, la_or, la_xor: 626 begin 627 case opnr of 628 0,2,3: 629 result:=oper[1]^.def; 630 else 631 internalerror(2013110106); 632 end; 633 end; 634 la_extractelement, la_insertelement, la_shufflevector, 635 la_extractvalue: 636 begin 637 { todo } 638 internalerror(2013110107); 639 end; 640 la_insertvalue: 641 begin 642 case opnr of 643 0,2: result:=oper[1]^.def; 644 else 645 internalerror(2013110108); 646 end; 647 end; 648 la_icmp, la_fcmp: 649 begin 650 case opnr of 651 0: result:=llvmbool1type; 652 3,4: result:=oper[2]^.def; 653 else 654 internalerror(2013110801); 655 end 656 end; 657 la_alloca: 658 begin 659 { shouldn't be spilled, the result of alloca should be read-only } 660 internalerror(2013110109); 661 end; 662 la_select: 663 begin 664 case opnr of 665 0,4,6: result:=oper[3]^.def; 666 2: result:=oper[1]^.def; 667 else 668 internalerror(2013110110); 669 end; 670 end; 671 la_blockaddress: 672 case opnr of 673 0: result:=voidcodepointertype 674 else 675 internalerror(2015111904); 676 end 677 else 678 internalerror(2013103101) 679 end; 680 end; 681 682 683 constructor taillvm.op_size(op : tllvmop; size: tdef); 684 begin 685 create_llvm(op); 686 ops:=1; 687 loaddef(0,size); 688 end; 689 690 691 constructor taillvm.op_reg_size(op: tllvmop; dst: tregister; size: tdef); 692 begin 693 create_llvm(op); 694 ops:=2; 695 loadreg(0,dst); 696 loaddef(1,size); 697 end; 698 699 700 constructor taillvm.op_ref_size(op: tllvmop; const dst: treference; size: tdef); 701 begin 702 create_llvm(op); 703 ops:=2; 704 loadref(0,dst); 705 loaddef(1,size); 706 end; 707 708 709 { %dst = add i32 %src1, %src2 } 710 constructor taillvm.op_reg_size_reg_reg(op: tllvmop; dst: tregister;size: tdef; src1, src2: tregister); 711 begin 712 create_llvm(op); 713 ops:=4; 714 loadreg(0,dst); 715 loaddef(1,size); 716 loadreg(2,src1); 717 loadreg(3,src2); 718 end; 719 720 { %dst = shl i32 %reg, 1 (= %reg shl 1) } 721 constructor taillvm.op_reg_size_reg_const(op: tllvmop; dst: tregister; size: tdef; src1: tregister; src2: int64); 722 begin 723 create_llvm(op); 724 ops:=4; 725 loadreg(0,dst); 726 loaddef(1,size); 727 loadreg(2,src1); 728 loadconst(3,src2); 729 end; 730 731 732 { %dst = sub i32 1, %src (= 1 - %src) } 733 constructor taillvm.op_reg_size_const_reg(op: tllvmop; dst: tregister; size: tdef; src1: int64; src2: tregister); 734 begin 735 create_llvm(op); 736 ops:=4; 737 loadreg(0,dst); 738 loaddef(1,size); 739 loadconst(2,src1); 740 loadreg(3,src2); 741 end; 742 743 744 { %dst = bitcast i32 %src to i8 } 745 constructor taillvm.op_reg_size_reg_size(op: tllvmop; dst: tregister; fromsize: tdef; src: tregister; tosize: tdef); 746 begin 747 create_llvm(op); 748 ops:=4; 749 loadreg(0,dst); 750 loaddef(1,fromsize); 751 loadreg(2,src); 752 loaddef(3,tosize); 753 end; 754 755 756 { %dst = bitcast i32 -1 to i8 } 757 constructor taillvm.op_reg_size_const_size(op: tllvmop; dst: tregister; fromsize: tdef; src: int64; tosize: tdef); 758 begin 759 create_llvm(op); 760 ops:=4; 761 loadreg(0,dst); 762 loaddef(1,fromsize); 763 loadconst(2,src); 764 loaddef(3,tosize); 765 end; 766 767 768 constructor taillvm.op_reg_size_fpconst_size(op: tllvmop; dst: tregister; fromsize: tdef; src: double; tosize: tdef); 769 begin 770 create_llvm(op); 771 ops:=4; 772 loadreg(0,dst); 773 loaddef(1,fromsize); 774 if fromsize.typ<>floatdef then 775 internalerror(2014012214); 776 case tfloatdef(fromsize).floattype of 777 s32real: 778 loadsingle(2,src); 779 s64real: 780 loaddouble(2,src); 781 else 782 internalerror(2014012215); 783 end; 784 loaddef(3,tosize); 785 end; 786 787 {$ifdef cpuextended} 788 constructor taillvm.op_reg_size_fpconst80_size(op: tllvmop; dst: tregister; fromsize: tdef; src: extended; tosize: tdef); 789 begin 790 create_llvm(op); 791 ops:=4; 792 loadreg(0,dst); 793 loaddef(1,fromsize); 794 loadextended(2,src); 795 loaddef(3,tosize); 796 end; 797 {$endif cpuextended} 798 799 800 constructor taillvm.op_reg_size_sym_size(op: tllvmop; dst: tregister; fromsize: tdef; src: TAsmSymbol; tosize: tdef); 801 begin 802 create_llvm(op); 803 ops:=4; 804 loadreg(0,dst); 805 loaddef(1,fromsize); 806 loadsymbol(2,src,0); 807 loaddef(3,tosize); 808 end; 809 810 811 constructor taillvm.op_reg_tai_size(op:tllvmop;dst:tregister;src:tai;tosize:tdef); 812 begin 813 create_llvm(op); 814 ops:=3; 815 loadreg(0,dst); 816 loadtai(1,src); 817 loaddef(2,tosize); 818 end; 819 820 821 constructor taillvm.op_reg_size_undef(op: tllvmop; dst: tregister; size: tdef); 822 begin 823 create_llvm(op); 824 ops:=4; 825 loadreg(0,dst); 826 loaddef(1,size); 827 loadundef(2); 828 loaddef(3,size); 829 end; 830 831 constructor taillvm.op_size_undef(op: tllvmop; size: tdef); 832 begin 833 create_llvm(op); 834 ops:=2; 835 loaddef(0,size); 836 loadundef(1); 837 end; 838 839 840 constructor taillvm.op_reg_size_ref_size(op: tllvmop; dst: tregister; fromsize: tdef; const src: treference; tosize: tdef); 841 begin 842 create_llvm(op); 843 ops:=4; 844 loadreg(0,dst); 845 loaddef(1,fromsize); 846 loadref(2,src); 847 loaddef(3,tosize); 848 end; 849 850 851 { store i32 3, i32* %ptr } 852 constructor taillvm.op_size_reg_size_ref(op: tllvmop; fromsize: tdef; src: tregister; ptrsize: tdef; const toref: treference); 853 begin 854 create_llvm(op); 855 ops:=4; 856 loaddef(0,fromsize); 857 loadreg(1,src); 858 loaddef(2,ptrsize); 859 loadref(3,toref); 860 end; 861 862 863 constructor taillvm.op_size_ref_size_ref(op: tllvmop; fromsize: tdef; const src: treference; ptrsize: tdef; const toref: treference); 864 begin 865 create_llvm(op); 866 ops:=4; 867 loaddef(0,fromsize); 868 loadref(1,src); 869 loaddef(2,ptrsize); 870 loadref(3,toref); 871 end; 872 873 874 constructor taillvm.op_size_const_size_ref(op: tllvmop; fromsize: tdef; src: int64; ptrsize: tdef; const toref: treference); 875 begin 876 create_llvm(op); 877 ops:=4; 878 loaddef(0,fromsize); 879 loadconst(1,src); 880 loaddef(2,ptrsize); 881 loadref(3,toref); 882 end; 883 884 885 constructor taillvm.op_reg_size_ref(op: tllvmop; dst: tregister; fromsize: tdef; const fromref: treference); 886 begin 887 create_llvm(op); 888 ops:=3; 889 loadreg(0,dst); 890 loaddef(1,fromsize); 891 loadref(2,fromref); 892 end; 893 894 895 constructor taillvm.op_reg_cond_size_reg_reg(op: tllvmop; dst: tregister; cmpcond: topcmp; size: tdef; reg1, reg2: tregister); 896 begin 897 create_llvm(op); 898 ops:=5; 899 loadreg(0,dst); 900 loadcond(1,cmpcond); 901 loaddef(2,size); 902 loadreg(3,reg1); 903 loadreg(4,reg2); 904 end; 905 906 constructor taillvm.op_reg_cond_size_reg_const(op: tllvmop; dst: tregister; cmpcond: topcmp; size: tdef; reg1: tregister; cnst: int64); 907 begin 908 create_llvm(op); 909 ops:=5; 910 loadreg(0,dst); 911 loadcond(1,cmpcond); 912 loaddef(2,size); 913 loadreg(3,reg1); 914 loadconst(4,cnst); 915 end; 916 917 constructor taillvm.op_reg_fpcond_size_reg_reg(op: tllvmop; dst: tregister; cmpcond: tllvmfpcmp; size: tdef; reg1, reg2: tregister); 918 begin 919 create_llvm(op); 920 ops:=5; 921 loadreg(0,dst); 922 loadfpcond(1,cmpcond); 923 loaddef(2,size); 924 loadreg(3,reg1); 925 loadreg(4,reg2); 926 end; 927 928 929 constructor taillvm.op_lab(op: tllvmop; lab: tasmlabel); 930 begin 931 create_llvm(op); 932 ops:=1; 933 loadsymbol(0,lab,0); 934 end; 935 936 937 constructor taillvm.op_size_reg_lab_lab(op: tllvmop; fromsize: tdef; condreg: tregister; labtrue, labfalse: tasmlabel); 938 begin 939 create_llvm(op); 940 ops:=4; 941 loaddef(0,fromsize); 942 loadreg(1,condreg); 943 loadsymbol(2,labtrue,0); 944 loadsymbol(3,labfalse,0); 945 end; 946 947 948 constructor taillvm.op_size_reg(op: tllvmop; def: tdef; reg: tregister); 949 begin 950 create_llvm(op); 951 ops:=2; 952 loaddef(0,def); 953 loadreg(1,reg); 954 end; 955 956 957 constructor taillvm.getelementptr_reg_size_ref_size_reg(dst: tregister; ptrsize: tdef; const ref: treference; indextype: tdef; index1: tregister; indirect: boolean); 958 var 959 index: longint; 960 begin 961 create_llvm(la_getelementptr); 962 if indirect then 963 ops:=7 964 else 965 ops:=5; 966 loadreg(0,dst); 967 loaddef(1,ptrsize); 968 loadref(2,ref); 969 if indirect then 970 begin 971 loaddef(3,s32inttype); 972 loadconst(4,0); 973 index:=5; 974 end 975 else 976 index:=3; 977 loaddef(index,indextype); 978 loadreg(index+1,index1); 979 end; 980 981 982 constructor taillvm.getelementptr_reg_size_ref_size_const(dst: tregister; ptrsize: tdef; const ref: treference; indextype: tdef; index1: ptrint; indirect: boolean); 983 var 984 index: longint; 985 begin 986 create_llvm(la_getelementptr); 987 if indirect then 988 ops:=7 989 else 990 ops:=5; 991 loadreg(0,dst); 992 loaddef(1,ptrsize); 993 loadref(2,ref); 994 if indirect then 995 begin 996 loaddef(3,s32inttype); 997 loadconst(4,0); 998 index:=5; 999 end 1000 else 1001 index:=3; 1002 loaddef(index,indextype); 1003 loadconst(index+1,index1); 1004 end; 1005 1006 1007 constructor taillvm.getelementptr_reg_tai_size_const(dst: tregister; const ai: tai; indextype: tdef; index1: ptrint; indirect: boolean); 1008 var 1009 index: longint; 1010 begin 1011 create_llvm(la_getelementptr); 1012 if indirect then 1013 ops:=6 1014 else 1015 ops:=4; 1016 loadreg(0,dst); 1017 loadtai(1,ai); 1018 if indirect then 1019 begin 1020 loaddef(2,s32inttype); 1021 loadconst(3,0); 1022 index:=4; 1023 end 1024 else 1025 index:=2; 1026 loaddef(index,indextype); 1027 loadconst(index+1,index1); 1028 end; 1029 1030 constructor taillvm.blockaddress(fun, lab: tasmsymbol); 1031 begin 1032 create_llvm(la_blockaddress); 1033 ops:=2; 1034 loadsymbol(0,fun,0); 1035 loadsymbol(1,lab,0); 1036 end; 1037 1038 1039 constructor taillvm.landingpad(dst: tregister; def: tdef; firstclause: taillvm); 1040 begin 1041 create_llvm(la_landingpad); 1042 ops:=3; 1043 loadreg(0,dst); 1044 loaddef(1,def); 1045 loadtai(2,firstclause); 1046 end; 1047 1048 1049 constructor taillvm.exceptclause(op: tllvmop; def: tdef; kind: TAsmSymbol; nextclause: taillvm); 1050 begin 1051 create_llvm(op); 1052 ops:=3; 1053 loaddef(0,def); 1054 loadsymbol(1,kind,0); 1055 loadtai(2,nextclause); 1056 end; 1057 1058 1059 constructor taillvm.call_size_name_paras(callpd: tdef; dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist); 1060 begin 1061 create_llvm(la_call); 1062 ops:=5; 1063 { we need this in case the call symbol is an alias for a symbol with a 1064 different def in the same module (via "external"), because then we 1065 have to insert a type conversion later from the alias def to the 1066 call def here; we can't always do that at the point the call itself 1067 is generated, because the alias declaration may occur anywhere } 1068 loaddef(0,retsize); 1069 loadreg(1,dst); 1070 loaddef(2,callpd); 1071 loadsymbol(3,name,0); 1072 loadparas(4,paras); 1073 end; 1074 1075 1076 constructor taillvm.call_size_reg_paras(callpd: tdef; dst: tregister; retsize: tdef; reg: tregister; paras: tfplist); 1077 begin 1078 create_llvm(la_call); 1079 ops:=5; 1080 loaddef(0,retsize); 1081 loadreg(1,dst); 1082 loaddef(2,callpd); 1083 loadreg(3,reg); 1084 loadparas(4,paras); 1085 end; 1086 1087 1088 constructor taillvm.asm_paras(asmlist: tasmlist; paras: tfplist); 1089 begin 1090 create_llvm(la_asmblock); 1091 ops:=2; 1092 loadasmlist(0,asmlist); 1093 loadparas(1,paras); 1094 end; 1095 1096 end. 1097