1 module d.llvm.expression; 2 3 import d.llvm.local; 4 5 import d.ir.expression; 6 import d.ir.symbol; 7 import d.ir.type; 8 9 import source.location; 10 11 import util.visitor; 12 13 import llvm.c.core; 14 15 struct ExpressionGen { 16 private LocalPass pass; 17 alias pass this; 18 19 this(LocalPass pass) { 20 this.pass = pass; 21 } 22 23 LLVMValueRef visit(Expression e) { 24 if (auto ce = cast(CompileTimeExpression) e) { 25 // XXX: for some resaon, pass.pass is need as 26 // alias this doesn't kick in. 27 import d.llvm.constant; 28 return ConstantGen(pass.pass).visit(ce); 29 } 30 31 return this.dispatch!(function LLVMValueRef(Expression e) { 32 import source.exception; 33 throw new CompileException( 34 e.location, 35 typeid(e).toString() ~ " is not supported", 36 ); 37 })(e); 38 } 39 40 private LLVMValueRef addressOf(E)(E e) if (is(E : Expression)) in { 41 assert(e.isLvalue, "e must be an lvalue"); 42 } do { 43 return AddressOfGen(pass).visit(e); 44 } 45 46 private LLVMValueRef buildLoad(LLVMValueRef ptr, TypeQualifier q) { 47 auto l = LLVMBuildLoad(builder, ptr, ""); 48 final switch(q) with(TypeQualifier) { 49 case Mutable, Inout, Const: 50 break; 51 52 case Shared, ConstShared: 53 import llvm.c.target; 54 LLVMSetAlignment(l, LLVMABIAlignmentOfType(targetData, LLVMTypeOf(l))); 55 LLVMSetOrdering(l, LLVMAtomicOrdering.SequentiallyConsistent); 56 break; 57 58 case Immutable: 59 // TODO: !invariant.load 60 break; 61 } 62 63 return l; 64 } 65 66 private LLVMValueRef loadAddressOf(E)(E e) if (is(E : Expression)) in { 67 assert(e.isLvalue, "e must be an lvalue"); 68 } do { 69 auto q = e.type.qualifier; 70 return buildLoad(addressOf(e), q); 71 } 72 73 private LLVMValueRef buildStore(LLVMValueRef ptr, LLVMValueRef val, TypeQualifier q) { 74 auto s = LLVMBuildStore(builder, val, ptr); 75 final switch(q) with(TypeQualifier) { 76 case Mutable, Inout, Const: 77 break; 78 79 case Shared, ConstShared: 80 import llvm.c.target; 81 LLVMSetAlignment(s, LLVMABIAlignmentOfType(targetData, LLVMTypeOf(val))); 82 LLVMSetOrdering(s, LLVMAtomicOrdering.SequentiallyConsistent); 83 break; 84 85 case Immutable: 86 // TODO: !invariant.load 87 break; 88 } 89 90 return s; 91 } 92 93 private auto handleBinaryOp(alias LLVMBuildOp)(BinaryExpression e) { 94 // XXX: should be useless, but parameters's order of evaluation is bugguy. 95 auto lhs = visit(e.lhs); 96 auto rhs = visit(e.rhs); 97 98 return LLVMBuildOp(builder, lhs, rhs, ""); 99 } 100 101 private auto handleLogicalBinary(bool shortCircuitOnTrue)(BinaryExpression e) { 102 auto lhs = visit(e.lhs); 103 104 auto lhsBB = LLVMGetInsertBlock(builder); 105 auto fun = LLVMGetBasicBlockParent(lhsBB); 106 107 static if (shortCircuitOnTrue) { 108 auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "or_rhs"); 109 auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "or_merge"); 110 LLVMBuildCondBr(builder, lhs, mergeBB, rhsBB); 111 } else { 112 auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "and_rhs"); 113 auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "and_merge"); 114 LLVMBuildCondBr(builder, lhs, rhsBB, mergeBB); 115 } 116 117 // Emit rhs 118 LLVMPositionBuilderAtEnd(builder, rhsBB); 119 120 auto rhs = visit(e.rhs); 121 122 // Conclude that block. 123 LLVMBuildBr(builder, mergeBB); 124 125 // Codegen of lhs can change the current block, so we put everything in order. 126 rhsBB = LLVMGetInsertBlock(builder); 127 LLVMMoveBasicBlockAfter(mergeBB, rhsBB); 128 LLVMPositionBuilderAtEnd(builder, mergeBB); 129 130 // Generate phi to get the result. 131 import d.llvm.type; 132 auto phiNode = LLVMBuildPhi( 133 builder, 134 TypeGen(pass.pass).visit(e.type), 135 "", 136 ); 137 138 LLVMValueRef[2] incomingValues; 139 incomingValues[0] = lhs; 140 incomingValues[1] = rhs; 141 142 LLVMBasicBlockRef[2] incomingBlocks; 143 incomingBlocks[0] = lhsBB; 144 incomingBlocks[1] = rhsBB; 145 146 LLVMAddIncoming( 147 phiNode, 148 incomingValues.ptr, 149 incomingBlocks.ptr, 150 incomingValues.length, 151 ); 152 153 return phiNode; 154 } 155 156 LLVMValueRef visit(BinaryExpression e) { 157 final switch(e.op) with(BinaryOp) { 158 case Comma : 159 visit(e.lhs); 160 return visit(e.rhs); 161 162 case Assign : 163 auto lhs = addressOf(e.lhs); 164 auto rhs = visit(e.rhs); 165 166 buildStore(lhs, rhs, e.lhs.type.qualifier); 167 return rhs; 168 169 case Add : 170 return handleBinaryOp!LLVMBuildAdd(e); 171 172 case Sub : 173 return handleBinaryOp!LLVMBuildSub(e); 174 175 case Mul : 176 return handleBinaryOp!LLVMBuildMul(e); 177 178 case UDiv : 179 return handleBinaryOp!LLVMBuildUDiv(e); 180 181 case SDiv : 182 return handleBinaryOp!LLVMBuildSDiv(e); 183 184 case URem : 185 return handleBinaryOp!LLVMBuildURem(e); 186 187 case SRem : 188 return handleBinaryOp!LLVMBuildSRem(e); 189 190 case Pow : 191 assert(0, "Not implemented"); 192 193 case Or : 194 return handleBinaryOp!LLVMBuildOr(e); 195 196 case And : 197 return handleBinaryOp!LLVMBuildAnd(e); 198 199 case Xor : 200 return handleBinaryOp!LLVMBuildXor(e); 201 202 case LeftShift : 203 return handleBinaryOp!LLVMBuildShl(e); 204 205 case UnsignedRightShift : 206 return handleBinaryOp!LLVMBuildLShr(e); 207 208 case SignedRightShift : 209 return handleBinaryOp!LLVMBuildAShr(e); 210 211 case LogicalOr : 212 return handleLogicalBinary!true(e); 213 214 case LogicalAnd : 215 return handleLogicalBinary!false(e); 216 } 217 } 218 219 private LLVMValueRef handleComparison( 220 ICmpExpression e, 221 LLVMIntPredicate pred, 222 ) { 223 // XXX: should be useless, but parameters's order of evaluation 224 // not enforced by DMD. 225 auto lhs = visit(e.lhs); 226 auto rhs = visit(e.rhs); 227 228 return LLVMBuildICmp(builder, pred, lhs, rhs, ""); 229 } 230 231 private LLVMValueRef handleComparison( 232 ICmpExpression e, 233 LLVMIntPredicate signedPredicate, 234 LLVMIntPredicate unsignedPredicate, 235 ) { 236 auto t = e.lhs.type.getCanonical(); 237 if (t.kind == TypeKind.Builtin) { 238 return handleComparison( 239 e, 240 t.builtin.isSigned() 241 ? signedPredicate 242 : unsignedPredicate, 243 ); 244 } 245 246 if (t.kind == TypeKind.Pointer) { 247 return handleComparison(e, unsignedPredicate); 248 } 249 250 auto t1 = e.lhs.type.toString(context); 251 auto t2 = e.rhs.type.toString(context); 252 assert(0, "Can't compare " ~ t1 ~ " with " ~ t2); 253 } 254 255 LLVMValueRef visit(ICmpExpression e) { 256 final switch(e.op) with(ICmpOp) { 257 case Equal : 258 return handleComparison(e, LLVMIntPredicate.EQ); 259 260 case NotEqual : 261 return handleComparison(e, LLVMIntPredicate.NE); 262 263 case Greater : 264 return handleComparison(e, LLVMIntPredicate.SGT, LLVMIntPredicate.UGT); 265 266 case GreaterEqual : 267 return handleComparison(e, LLVMIntPredicate.SGE, LLVMIntPredicate.UGE); 268 269 case Less : 270 return handleComparison(e, LLVMIntPredicate.SLT, LLVMIntPredicate.ULT); 271 272 case LessEqual : 273 return handleComparison(e, LLVMIntPredicate.SLE, LLVMIntPredicate.ULE); 274 } 275 } 276 277 LLVMValueRef visit(UnaryExpression e) { 278 final switch(e.op) with(UnaryOp) { 279 case AddressOf : 280 return addressOf(e.expr); 281 282 case Dereference : 283 return buildLoad(visit(e.expr), e.type.qualifier); 284 285 case PreInc : 286 auto q = e.expr.type.qualifier; 287 auto ptr = addressOf(e.expr); 288 auto value = buildLoad(ptr, q); 289 auto type = LLVMTypeOf(value); 290 291 if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) { 292 auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), 1, true); 293 value = LLVMBuildInBoundsGEP(builder, value, &one, 1, ""); 294 } else { 295 value = LLVMBuildAdd(builder, value, LLVMConstInt(type, 1, true), ""); 296 } 297 298 LLVMBuildStore(builder, value, ptr); 299 return value; 300 301 case PreDec : 302 auto q = e.expr.type.qualifier; 303 auto ptr = addressOf(e.expr); 304 auto value = buildLoad(ptr, q); 305 auto type = LLVMTypeOf(value); 306 307 if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) { 308 auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true); 309 value = LLVMBuildInBoundsGEP(builder, value, &one, 1, ""); 310 } else { 311 value = LLVMBuildSub(builder, value, LLVMConstInt(type, 1, true), ""); 312 } 313 314 LLVMBuildStore(builder, value, ptr); 315 return value; 316 317 case PostInc : 318 auto q = e.expr.type.qualifier; 319 auto ptr = addressOf(e.expr); 320 auto value = buildLoad(ptr, q); 321 auto ret = value; 322 auto type = LLVMTypeOf(value); 323 324 if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) { 325 auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), 1, true); 326 value = LLVMBuildInBoundsGEP(builder, value, &one, 1, ""); 327 } else { 328 value = LLVMBuildAdd(builder, value, LLVMConstInt(type, 1, true), ""); 329 } 330 331 LLVMBuildStore(builder, value, ptr); 332 return ret; 333 334 case PostDec : 335 auto q = e.expr.type.qualifier; 336 auto ptr = addressOf(e.expr); 337 auto value = buildLoad(ptr, q); 338 auto ret = value; 339 auto type = LLVMTypeOf(value); 340 341 if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) { 342 auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true); 343 value = LLVMBuildInBoundsGEP(builder, value, &one, 1, ""); 344 } else { 345 value = LLVMBuildSub(builder, value, LLVMConstInt(type, 1, true), ""); 346 } 347 348 LLVMBuildStore(builder, value, ptr); 349 return ret; 350 351 case Plus : 352 return visit(e.expr); 353 354 case Minus : 355 import d.llvm.type; 356 return LLVMBuildSub( 357 builder, 358 LLVMConstInt(TypeGen(pass.pass).visit(e.type), 0, true), 359 visit(e.expr), 360 "", 361 ); 362 363 case Not : 364 import d.llvm.type; 365 return LLVMBuildICmp( 366 builder, 367 LLVMIntPredicate.EQ, 368 LLVMConstInt(TypeGen(pass.pass).visit(e.type), 0, true), 369 visit(e.expr), 370 "", 371 ); 372 373 case Complement : 374 import d.llvm.type; 375 return LLVMBuildXor( 376 builder, 377 visit(e.expr), 378 LLVMConstInt(TypeGen(pass.pass).visit(e.type), -1, true), 379 "", 380 ); 381 } 382 } 383 384 LLVMValueRef visit(TernaryExpression e) { 385 auto cond = visit(e.condition); 386 387 auto condBB = LLVMGetInsertBlock(builder); 388 auto fun = LLVMGetBasicBlockParent(condBB); 389 390 auto lhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_lhs"); 391 auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_rhs"); 392 auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_merge"); 393 394 LLVMBuildCondBr(builder, cond, lhsBB, rhsBB); 395 396 // Emit lhs 397 LLVMPositionBuilderAtEnd(builder, lhsBB); 398 auto lhs = visit(e.lhs); 399 // Conclude that block. 400 LLVMBuildBr(builder, mergeBB); 401 402 // Codegen of lhs can change the current block, so we put everything in order. 403 lhsBB = LLVMGetInsertBlock(builder); 404 LLVMMoveBasicBlockAfter(rhsBB, lhsBB); 405 406 // Emit rhs 407 LLVMPositionBuilderAtEnd(builder, rhsBB); 408 auto rhs = visit(e.rhs); 409 // Conclude that block. 410 LLVMBuildBr(builder, mergeBB); 411 412 // Codegen of rhs can change the current block, so we put everything in order. 413 rhsBB = LLVMGetInsertBlock(builder); 414 LLVMMoveBasicBlockAfter(mergeBB, rhsBB); 415 416 // Generate phi to get the result. 417 LLVMPositionBuilderAtEnd(builder, mergeBB); 418 419 import d.llvm.type; 420 auto phiNode = LLVMBuildPhi( 421 builder, 422 TypeGen(pass.pass).visit(e.type), 423 "", 424 ); 425 426 LLVMValueRef[2] incomingValues; 427 incomingValues[0] = lhs; 428 incomingValues[1] = rhs; 429 430 LLVMBasicBlockRef[2] incomingBlocks; 431 incomingBlocks[0] = lhsBB; 432 incomingBlocks[1] = rhsBB; 433 434 LLVMAddIncoming( 435 phiNode, 436 incomingValues.ptr, 437 incomingBlocks.ptr, 438 incomingValues.length, 439 ); 440 441 return phiNode; 442 } 443 444 LLVMValueRef visit(VariableExpression e) { 445 return (e.var.storage == Storage.Enum || e.var.isFinal) 446 ? declare(e.var) 447 : loadAddressOf(e); 448 } 449 450 LLVMValueRef visit(FieldExpression e) { 451 if (e.isLvalue) { 452 return loadAddressOf(e); 453 } 454 455 assert(e.expr.type.kind != TypeKind.Union, "rvalue unions not implemented."); 456 return LLVMBuildExtractValue(builder, visit(e.expr), e.field.index, ""); 457 } 458 459 LLVMValueRef visit(FunctionExpression e) { 460 return declare(e.fun); 461 } 462 463 LLVMValueRef visit(DelegateExpression e) { 464 auto type = e.type.getCanonical().asFunctionType(); 465 auto tCtxs = type.contexts; 466 auto eCtxs = e.contexts; 467 468 auto length = cast(uint) tCtxs.length; 469 assert(eCtxs.length == length); 470 471 import d.llvm.type; 472 auto dg = LLVMGetUndef(TypeGen(pass.pass).visit(type)); 473 474 foreach (i, c; eCtxs) { 475 auto ctxValue = tCtxs[i].isRef 476 ? addressOf(c) 477 : visit(c); 478 479 dg = LLVMBuildInsertValue(builder, dg, ctxValue, cast(uint) i, ""); 480 } 481 482 LLVMValueRef fun; 483 if (auto m = cast(Method) e.method) { 484 assert(m.hasThis); 485 assert( 486 eCtxs[m.hasContext].type.getCanonical().dclass, 487 "Virtual dispatch can only be done on classes" 488 ); 489 490 auto thisPtr = LLVMBuildExtractValue(builder, dg, m.hasContext, ""); 491 auto vtblPtr = LLVMBuildStructGEP(builder, thisPtr, 0, ""); 492 auto vtbl = LLVMBuildLoad(builder, vtblPtr, "vtbl"); 493 auto funPtr = LLVMBuildStructGEP(builder, vtbl, m.index, ""); 494 fun = LLVMBuildLoad(builder, funPtr, ""); 495 } else { 496 fun = declare(e.method); 497 } 498 499 dg = LLVMBuildInsertValue(builder, dg, fun, length, ""); 500 return dg; 501 } 502 503 LLVMValueRef visit(NewExpression e) { 504 auto ctor = declare(e.ctor); 505 506 import std.algorithm, std.array; 507 auto args = e.args.map!(a => visit(a)).array(); 508 509 import d.llvm.type; 510 auto type = TypeGen(pass.pass).visit(e.type); 511 LLVMValueRef size = LLVMSizeOf( 512 (e.type.kind == TypeKind.Class) 513 ? LLVMGetElementType(type) 514 : type, 515 ); 516 517 auto allocFun = declare(pass.object.getGCThreadLocalAllow()); 518 auto alloc = buildCall(allocFun, [size]); 519 auto ptr = LLVMBuildPointerCast(builder, alloc, type, ""); 520 521 // XXX: This should be set on the alloc function instead of the callsite. 522 LLVMAddCallSiteAttribute( 523 alloc, 524 LLVMAttributeReturnIndex, 525 getAttribute("noalias"), 526 ); 527 528 auto thisArg = visit(e.dinit); 529 auto thisType = LLVMTypeOf(LLVMGetFirstParam(ctor)); 530 bool isClass = LLVMGetTypeKind(thisType) == LLVMTypeKind.Pointer; 531 if (isClass) { 532 auto ptrType = LLVMPointerType(LLVMTypeOf(thisArg), 0); 533 auto thisPtr = LLVMBuildBitCast(builder, ptr, ptrType, ""); 534 LLVMBuildStore(builder, thisArg, thisPtr); 535 thisArg = LLVMBuildBitCast(builder, ptr, thisType, ""); 536 } 537 538 args = thisArg ~ args; 539 auto obj = buildCall(ctor, args); 540 if (!isClass) { 541 LLVMBuildStore(builder, obj, ptr); 542 } 543 544 return ptr; 545 } 546 547 LLVMValueRef visit(IndexExpression e) in { 548 assert(e.isLvalue, "e must be an lvalue"); 549 } do { 550 return loadAddressOf(e); 551 } 552 553 auto genBoundCheck(Location location, LLVMValueRef condition) { 554 auto fun = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); 555 556 auto failBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "bound_fail"); 557 auto okBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "bound_ok"); 558 559 auto br = LLVMBuildCondBr(builder, condition, okBB, failBB); 560 561 // We assume that bound check fail is unlikely. 562 LLVMSetMetadata(br, profKindID, unlikelyBranch); 563 564 // Emit bound check fail code. 565 LLVMPositionBuilderAtEnd(builder, failBB); 566 567 auto floc = location.getFullLocation(context); 568 569 LLVMValueRef[2] args; 570 args[0] = buildDString(floc.getSource().getFileName().toString()); 571 args[1] = LLVMConstInt( 572 LLVMInt32TypeInContext(llvmCtx), 573 floc.getStartLineNumber(), 574 false, 575 ); 576 577 buildCall(declare(pass.object.getArrayOutOfBounds()), args); 578 579 LLVMBuildUnreachable(builder); 580 581 // And continue regular program flow. 582 LLVMPositionBuilderAtEnd(builder, okBB); 583 } 584 585 LLVMValueRef visit(SliceExpression e) { 586 auto t = e.sliced.type.getCanonical(); 587 588 LLVMValueRef length, ptr; 589 if (t.kind == TypeKind.Slice) { 590 auto slice = visit(e.sliced); 591 592 length = LLVMBuildExtractValue(builder, slice, 0, ".length"); 593 ptr = LLVMBuildExtractValue(builder, slice, 1, ".ptr"); 594 } else if (t.kind == TypeKind.Pointer) { 595 ptr = visit(e.sliced); 596 } else if (t.kind == TypeKind.Array) { 597 length = LLVMConstInt(LLVMInt64TypeInContext(llvmCtx), t.size, false); 598 599 import d.llvm.type; 600 auto ptrType = LLVMPointerType(TypeGen(pass.pass).visit(t.element), 0); 601 ptr = LLVMBuildBitCast(builder, addressOf(e.sliced), ptrType, ""); 602 } else { 603 assert(0, "Don't know how to slice " ~ e.type.toString(context)); 604 } 605 606 auto i64 = LLVMInt64TypeInContext(llvmCtx); 607 auto first = LLVMBuildZExt(builder, visit(e.first), i64, ""); 608 auto second = LLVMBuildZExt(builder, visit(e.second), i64, ""); 609 610 auto condition = LLVMBuildICmp(builder, LLVMIntPredicate.ULE, first, second, ""); 611 if (length) { 612 auto boundCheck = LLVMBuildICmp(builder, LLVMIntPredicate.ULE, second, length, ""); 613 condition = LLVMBuildAnd(builder, condition, boundCheck, ""); 614 } 615 616 genBoundCheck(e.location, condition); 617 618 import d.llvm.type; 619 auto slice = LLVMGetUndef(TypeGen(pass.pass).visit(e.type)); 620 621 auto sub = LLVMBuildSub(builder, second, first, ""); 622 slice = LLVMBuildInsertValue(builder, slice, sub, 0, ""); 623 624 ptr = LLVMBuildInBoundsGEP(builder, ptr, &first, 1, ""); 625 slice = LLVMBuildInsertValue(builder, slice, ptr, 1, ""); 626 627 return slice; 628 } 629 630 // FIXME: This is public because of intrinsic codegen. 631 // Once we support sequence return, we can make that private. 632 LLVMValueRef buildBitCast(LLVMValueRef v, LLVMTypeRef t) { 633 auto k = LLVMGetTypeKind(t); 634 if (k != LLVMTypeKind.Struct) { 635 assert(k != LLVMTypeKind.Array); 636 return LLVMBuildBitCast(builder, v, t, ""); 637 } 638 639 auto vt = LLVMTypeOf(v); 640 assert(LLVMGetTypeKind(vt) == LLVMTypeKind.Struct); 641 642 auto count = LLVMCountStructElementTypes(t); 643 assert(LLVMCountStructElementTypes(vt) == count); 644 645 LLVMTypeRef[] types; 646 types.length = count; 647 648 LLVMGetStructElementTypes(t, types.ptr); 649 650 auto ret = LLVMGetUndef(t); 651 foreach (i; 0 .. count) { 652 ret = LLVMBuildInsertValue(builder, ret, buildBitCast( 653 LLVMBuildExtractValue(builder, v, i, ""), 654 types[i], 655 ), i, ""); 656 } 657 658 return ret; 659 } 660 661 LLVMValueRef visit(CastExpression e) { 662 import d.llvm.type; 663 auto type = TypeGen(pass.pass).visit(e.type); 664 auto value = visit(e.expr); 665 666 final switch(e.kind) with(CastKind) { 667 case Exact, Qual : 668 return value; 669 670 case Bit : 671 return buildBitCast(value, type); 672 673 case UPad : 674 return LLVMBuildZExt(builder, value, type, ""); 675 676 case SPad : 677 return LLVMBuildSExt(builder, value, type, ""); 678 679 case Trunc : 680 return LLVMBuildTrunc(builder, value, type, ""); 681 682 case IntToPtr : 683 return LLVMBuildIntToPtr(builder, value, type, ""); 684 685 case PtrToInt : 686 return LLVMBuildPtrToInt(builder, value, type, ""); 687 688 case IntToBool : 689 return LLVMBuildICmp( 690 builder, 691 LLVMIntPredicate.NE, 692 value, 693 LLVMConstInt(LLVMTypeOf(value), 0, false), 694 "", 695 ); 696 697 case Down : 698 import d.llvm.type; 699 auto obj = TypeGen(pass.pass).visit(pass.object.getObject()); 700 701 LLVMValueRef[2] args; 702 args[0] = LLVMBuildBitCast(builder, value, obj, ""); 703 args[1] = getTypeid(e.type); 704 705 auto result = buildCall(declare(pass.object.getClassDowncast()), args[]); 706 return LLVMBuildBitCast(builder, result, type, ""); 707 708 case Invalid : 709 assert(0, "Invalid cast"); 710 } 711 } 712 713 LLVMValueRef visit(ArrayLiteral e) { 714 auto t = e.type; 715 auto count = cast(uint) e.values.length; 716 717 import d.llvm.type; 718 auto et = TypeGen(pass.pass).visit(t.element); 719 auto type = LLVMArrayType(et, count); 720 auto array = LLVMGetUndef(type); 721 722 uint i = 0; 723 import std.algorithm; 724 foreach(v; e.values.map!(v => visit(v))) { 725 array = LLVMBuildInsertValue(builder, array, v, i++, ""); 726 } 727 728 if (t.kind == TypeKind.Array) { 729 return array; 730 } 731 732 auto ptrType = LLVMPointerType(type, 0); 733 auto ptr = LLVMConstNull(ptrType); 734 735 if (count > 0) { 736 // We have a slice, we need to allocate. 737 auto allocFun = declare(pass.object.getGCThreadLocalAllow()); 738 auto alloc = buildCall(allocFun, [LLVMSizeOf(type)]); 739 ptr = LLVMBuildPointerCast(builder, alloc, ptrType, ""); 740 741 // XXX: This should be set on the alloc function instead of the callsite. 742 LLVMAddCallSiteAttribute( 743 alloc, 744 LLVMAttributeReturnIndex, 745 getAttribute("noalias"), 746 ); 747 748 // Store all the values on heap. 749 LLVMBuildStore(builder, array, ptr); 750 } 751 752 // Build the slice. 753 auto slice = LLVMGetUndef(TypeGen(pass.pass).visit(t)); 754 auto i64 = LLVMInt64TypeInContext(llvmCtx); 755 auto llvmCount = LLVMConstInt(i64, count, false); 756 slice = LLVMBuildInsertValue(builder, slice, llvmCount, 0, ""); 757 758 auto elPtrType = LLVMPointerType(et, 0); 759 ptr = LLVMBuildPointerCast(builder, ptr, elPtrType, ""); 760 slice = LLVMBuildInsertValue(builder, slice, ptr, 1, ""); 761 762 return slice; 763 } 764 765 auto buildCall(LLVMValueRef callee, LLVMValueRef[] args) { 766 // Check if we need to invoke. 767 if (!lpBB) { 768 return LLVMBuildCall( 769 builder, 770 callee, 771 args.ptr, 772 cast(uint) args.length, 773 "", 774 ); 775 } 776 777 auto currentBB = LLVMGetInsertBlock(builder); 778 auto fun = LLVMGetBasicBlockParent(currentBB); 779 auto thenBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "then"); 780 auto ret = LLVMBuildInvoke( 781 builder, 782 callee, 783 args.ptr, 784 cast(uint) args.length, 785 thenBB, 786 lpBB, 787 "", 788 ); 789 790 LLVMMoveBasicBlockAfter(thenBB, currentBB); 791 LLVMPositionBuilderAtEnd(builder, thenBB); 792 793 return ret; 794 } 795 796 private LLVMValueRef buildCall(CallExpression c) { 797 auto cType = c.callee.type.getCanonical().asFunctionType(); 798 auto contexts = cType.contexts; 799 auto params = cType.parameters; 800 801 LLVMValueRef[] args; 802 args.length = contexts.length + c.args.length; 803 804 auto callee = visit(c.callee); 805 foreach (i, ctx; contexts) { 806 args[i] = LLVMBuildExtractValue(builder, callee, cast(uint) i, ""); 807 } 808 809 auto firstarg = contexts.length; 810 if (firstarg) { 811 callee = LLVMBuildExtractValue(builder, callee, cast(uint) contexts.length, ""); 812 } 813 814 uint i = 0; 815 foreach(t; params) { 816 args[i + firstarg] = t.isRef 817 ? addressOf(c.args[i]) 818 : visit(c.args[i]); 819 i++; 820 } 821 822 // Handle variadic functions. 823 while(i < c.args.length) { 824 args[i + firstarg] = visit(c.args[i]); 825 i++; 826 } 827 828 return buildCall(callee, args); 829 } 830 831 LLVMValueRef visit(CallExpression c) { 832 return c.callee.type.asFunctionType().returnType.isRef 833 ? LLVMBuildLoad(builder, buildCall(c), "") 834 : buildCall(c); 835 } 836 837 LLVMValueRef visit(IntrinsicExpression e) { 838 import d.llvm.intrinsic, d.llvm.type; 839 return buildBitCast( 840 IntrinsicGen(pass).build(e.intrinsic, e.args), 841 // XXX: This is necessary until returning sequence is supported. 842 TypeGen(pass.pass).visit(e.type), 843 ); 844 } 845 846 LLVMValueRef visit(TupleExpression e) { 847 import d.llvm.type; 848 auto tuple = LLVMGetUndef(TypeGen(pass.pass).visit(e.type)); 849 850 uint i = 0; 851 import std.algorithm; 852 foreach(v; e.values.map!(v => visit(v))) { 853 tuple = LLVMBuildInsertValue(builder, tuple, v, i++, ""); 854 } 855 856 return tuple; 857 } 858 859 LLVMValueRef visit(DynamicTypeidExpression e) { 860 auto vtblPtr = LLVMBuildStructGEP(builder, visit(e.argument), 0, ""); 861 auto vtbl = LLVMBuildLoad(builder, vtblPtr, ""); 862 863 import d.llvm.type; 864 auto classInfo = TypeGen(pass.pass).visit(pass.object.getClassInfo()); 865 866 // The classInfo is just before the vtbls in memory. 867 // So we cast the pointer and look at index -1 to get it. 868 auto ptr = LLVMBuildBitCast(builder, vtbl, classInfo, ""); 869 auto idx = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true); 870 return LLVMBuildGEP(builder, ptr, &idx, 1, ""); 871 } 872 873 private LLVMValueRef getTypeid(Type t) { 874 t = t.getCanonical(); 875 assert(t.kind == TypeKind.Class, "Not implemented"); 876 877 // Ensure that the thing is generated. 878 auto c = t.dclass; 879 880 import d.llvm.type; 881 TypeGen(pass.pass).visit(c); 882 883 return TypeGen(pass.pass).getTypeInfo(c); 884 } 885 886 LLVMValueRef visit(StaticTypeidExpression e) { 887 return getTypeid(e.argument); 888 } 889 890 LLVMValueRef visit(VtblExpression e) { 891 // Vtbl do not have a known type in D, so we need to cast. 892 import d.llvm.type; 893 return LLVMBuildPointerCast( 894 builder, 895 TypeGen(pass.pass).getVtbl(e.dclass), 896 TypeGen(pass.pass).visit(e.type), 897 "", 898 ); 899 } 900 } 901 902 struct AddressOfGen { 903 private LocalPass pass; 904 alias pass this; 905 906 this(LocalPass pass) { 907 this.pass = pass; 908 } 909 910 LLVMValueRef visit(Expression e) in { 911 assert(e.isLvalue, "You can only compute addresses of lvalues."); 912 } do { 913 return this.dispatch(e); 914 } 915 916 private LLVMValueRef valueOf(E)(E e) if (is(E : Expression)) { 917 return ExpressionGen(pass).visit(e); 918 } 919 920 LLVMValueRef visit(VariableExpression e) in { 921 assert(e.var.storage != Storage.Enum, "enum have no address."); 922 assert(!e.var.isFinal, "finals have no address."); 923 } do { 924 return declare(e.var); 925 } 926 927 LLVMValueRef visit(FieldExpression e) { 928 auto base = e.expr; 929 auto type = base.type.getCanonical(); 930 931 LLVMValueRef ptr; 932 switch(type.kind) with(TypeKind) { 933 case Slice, Struct, Union: 934 ptr = visit(base); 935 break; 936 937 // XXX: Remove pointer. libd do not dererefence as expected. 938 case Pointer, Class: 939 ptr = valueOf(base); 940 break; 941 942 default: 943 assert( 944 0, 945 "Address of field only work on aggregate types, not " 946 ~ type.toString(context)); 947 } 948 949 // Make the type is not opaque. 950 // XXX: Find a factorized way to load and gep that ensure 951 // the indexed is not opaque and load metadata are correct. 952 import d.llvm.type; 953 TypeGen(pass.pass).visit(type); 954 955 ptr = LLVMBuildStructGEP(builder, ptr, e.field.index, ""); 956 if (type.kind != TypeKind.Union) { 957 return ptr; 958 } 959 960 return LLVMBuildBitCast( 961 builder, 962 ptr, 963 LLVMPointerType(TypeGen(pass.pass).visit(e.type), 0), 964 "", 965 ); 966 } 967 968 LLVMValueRef visit(ContextExpression e) in { 969 assert( 970 e.type.kind == TypeKind.Context, 971 "ContextExpression must be of ContextType" 972 ); 973 } do { 974 return pass.getContext(e.type.context); 975 } 976 977 LLVMValueRef visit(UnaryExpression e) { 978 if (e.op == UnaryOp.Dereference) { 979 return valueOf(e.expr); 980 } 981 982 assert(0, "not an lvalue ??"); 983 } 984 985 LLVMValueRef visit(CastExpression e) { 986 import d.llvm.type; 987 auto type = TypeGen(pass.pass).visit(e.type); 988 auto value = visit(e.expr); 989 990 final switch(e.kind) with(CastKind) { 991 case Exact, Qual : 992 return value; 993 994 case Bit : 995 return LLVMBuildBitCast( 996 builder, 997 value, 998 LLVMPointerType(type, 0), 999 "", 1000 ); 1001 1002 case Invalid, IntToPtr, PtrToInt, Down : 1003 case IntToBool, Trunc, SPad, UPad : 1004 assert(0, "Not an lvalue"); 1005 } 1006 } 1007 1008 LLVMValueRef visit(CallExpression c) { 1009 return ExpressionGen(pass).buildCall(c); 1010 } 1011 1012 LLVMValueRef visit(IndexExpression e) { 1013 return computeIndexPtr(e.location, e.indexed, e.index); 1014 } 1015 1016 auto computeIndexPtr(Location location, Expression indexed, Expression index) { 1017 auto t = indexed.type.getCanonical(); 1018 if (t.kind == TypeKind.Slice) { 1019 auto slice = valueOf(indexed); 1020 auto i64 = LLVMInt64TypeInContext(llvmCtx); 1021 auto i = LLVMBuildZExt(builder, valueOf(index), i64, ""); 1022 auto length = LLVMBuildExtractValue(builder, slice, 0, ".length"); 1023 auto condition = LLVMBuildICmp(builder, LLVMIntPredicate.ULT, i, length, ""); 1024 genBoundCheck(location, condition); 1025 1026 auto ptr = LLVMBuildExtractValue(builder, slice, 1, ".ptr"); 1027 return LLVMBuildInBoundsGEP(builder, ptr, &i, 1, ""); 1028 } else if (t.kind == TypeKind.Pointer) { 1029 auto ptr = valueOf(indexed); 1030 auto i = valueOf(index); 1031 return LLVMBuildInBoundsGEP(builder, ptr, &i, 1, ""); 1032 } else if (t.kind == TypeKind.Array) { 1033 auto ptr = visit(indexed); 1034 auto i = valueOf(index); 1035 1036 auto i64 = LLVMInt64TypeInContext(llvmCtx); 1037 auto condition = LLVMBuildICmp( 1038 builder, 1039 LLVMIntPredicate.ULT, 1040 LLVMBuildZExt(builder, i, i64, ""), 1041 LLVMConstInt(LLVMInt64TypeInContext(llvmCtx), t.size, false), 1042 "", 1043 ); 1044 1045 genBoundCheck(location, condition); 1046 1047 LLVMValueRef[2] indices; 1048 indices[0] = LLVMConstInt(i64, 0, false); 1049 indices[1] = i; 1050 1051 return LLVMBuildInBoundsGEP(builder, ptr, indices.ptr, indices.length, ""); 1052 } 1053 1054 assert(0, "Don't know how to index " ~ indexed.type.toString(context)); 1055 } 1056 1057 auto genBoundCheck(Location location, LLVMValueRef condition) { 1058 return ExpressionGen(pass).genBoundCheck(location, condition); 1059 } 1060 }