diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 690198dd74..43e6949e99 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -590,11 +590,11 @@ void initializeArrayLiteral(IRState *p, ArrayLiteralExp *ale, LLValue *dstMem) { } else { // Store the elements one by one. for (size_t i = 0; i < elemCount; ++i) { - DValue *e = toElem(indexArrayLiteral(ale, i)); + DValue *rhs = toElem(indexArrayLiteral(ale, i)); - LLValue *elemAddr = DtoGEPi(dstMem, 0, i, "", p->scopebb()); - auto vv = new DLValue(e->type, elemAddr); - DtoAssign(ale->loc, vv, e, TOKconstruct, true); + LLValue *lhsPtr = DtoGEPi(dstMem, 0, i, "", p->scopebb()); + DLValue lhs(rhs->type, DtoBitCast(lhsPtr, DtoPtrToType(rhs->type))); + DtoAssign(ale->loc, &lhs, rhs, TOKconstruct, true); } } } diff --git a/gen/binops.cpp b/gen/binops.cpp index 7f365ac4fe..bf34167fda 100644 --- a/gen/binops.cpp +++ b/gen/binops.cpp @@ -261,8 +261,8 @@ DValue *binBitwise(Loc &loc, Type *type, Expression *lhs, Expression *rhs, bool loadLhsAfterRhs) { auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs); - LLValue *l = DtoRVal(rvals.lhs); - LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, lhs->type)); + LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type)); + LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type)); LLValue *res = llvm::BinaryOperator::Create(binOp, l, r, "", gIR->scopebb()); return new DImValue(type, res); diff --git a/gen/dvalue.cpp b/gen/dvalue.cpp index 2945f127ff..0aaaa86f4d 100644 --- a/gen/dvalue.cpp +++ b/gen/dvalue.cpp @@ -60,12 +60,24 @@ DRValue::DRValue(Type *t, LLValue *v) : DValue(t, v) { //////////////////////////////////////////////////////////////////////////////// -DConstValue::DConstValue(Type *t, LLConstant *con) : DRValue(t, con) {} +DImValue::DImValue(Type *t, llvm::Value *v) : DRValue(t, v) { + // TODO: get rid of Tfunction exception + assert(t->toBasetype()->ty == Tfunction || v->getType() == DtoType(t)); +} + +//////////////////////////////////////////////////////////////////////////////// + +DConstValue::DConstValue(Type *t, LLConstant *con) : DRValue(t, con) { + assert(con->getType() == DtoType(t)); +} //////////////////////////////////////////////////////////////////////////////// DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr) - : DRValue(t, DtoAggrPair(length, ptr)) {} + : DRValue(t, DtoAggrPair(length, ptr)) { + assert(t->toBasetype()->ty == Tarray && + ptr->getType() == DtoPtrToType(t->toBasetype()->nextOf())); +} LLValue *DSliceValue::getLength() { return DtoExtractValue(val, 0, ".len"); } @@ -77,7 +89,7 @@ DFuncValue::DFuncValue(Type *t, FuncDeclaration *fd, LLValue *v, LLValue *vt) : DRValue(t, v), func(fd), vthis(vt) {} DFuncValue::DFuncValue(FuncDeclaration *fd, LLValue *v, LLValue *vt) - : DRValue(fd->type, v), func(fd), vthis(vt) {} + : DFuncValue(fd->type, fd, v, vt) {} bool DFuncValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val) && @@ -86,31 +98,8 @@ bool DFuncValue::definedInFuncEntryBB() { //////////////////////////////////////////////////////////////////////////////// -static bool checkVarValueType(LLType *t, bool extraDeref) { - if (extraDeref) { - llvm::PointerType *pt = llvm::dyn_cast(t); - if (!pt) { - return false; - } - - t = pt->getElementType(); - } - - llvm::PointerType *pt = llvm::dyn_cast(t); - if (!pt) { - return false; - } - - // bools should not be stored as i1 any longer. - if (pt->getElementType() == llvm::Type::getInt1Ty(gIR->context())) { - return false; - } - - return true; -} - DLValue::DLValue(Type *t, LLValue *v) : DValue(t, v) { - assert(checkVarValueType(v->getType(), false)); + assert(t->toBasetype()->ty == Ttuple || v->getType() == DtoPtrToType(t)); } DRValue *DLValue::getRVal() { @@ -131,7 +120,7 @@ DRValue *DLValue::getRVal() { //////////////////////////////////////////////////////////////////////////////// DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) { - assert(checkVarValueType(v->getType(), true)); + assert(v->getType() == DtoPtrToType(t)->getPointerTo()); } DRValue *DSpecialRefValue::getRVal() { diff --git a/gen/dvalue.h b/gen/dvalue.h index 2e21dac1e1..4cc1ff95a4 100644 --- a/gen/dvalue.h +++ b/gen/dvalue.h @@ -93,7 +93,7 @@ protected: /// integral and floating-point types. class DImValue : public DRValue { public: - DImValue(Type *t, llvm::Value *v) : DRValue(t, v) {} + DImValue(Type *t, llvm::Value *v); DImValue *isIm() override { return this; } }; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index a590018e09..9523cba3ac 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -396,7 +396,7 @@ DValue *DtoNullValue(Type *type, Loc loc) { // representation if (basetype->isintegral() || basetype->isfloating() || basety == Tpointer || basety == Tclass || basety == Tdelegate || basety == Taarray) { - return new DConstValue(type, LLConstant::getNullValue(lltype)); + return new DNullValue(type, LLConstant::getNullValue(lltype)); } // dynamic array if (basety == Tarray) { @@ -1553,7 +1553,7 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) { assert(!isSpecialRefVar(vd) && "Code not expected to handle special " "ref vars, although it can easily be " "made to."); - return new DLValue(type, getIrValue(vd)); + return new DLValue(type, DtoBitCast(getIrValue(vd), DtoPtrToType(type))); } else { Logger::println("a normal variable"); @@ -1806,22 +1806,28 @@ DValue *makeVarDValue(Type *type, VarDeclaration *vd, llvm::Value *storage) { val = getIrValue(vd); } - if (vd->isDataseg() || (vd->storage_class & STCextern)) { - // The type of globals is determined by their initializer, so - // we might need to cast. Make sure that the type sizes fit - - // '==' instead of '<=' should probably work as well. - llvm::Type *expectedType = llvm::PointerType::getUnqual(DtoMemType(type)); + // We might need to cast. + llvm::Type *expectedType = DtoPtrToType(type); + const bool isSpecialRef = isSpecialRefVar(vd); + if (isSpecialRef) + expectedType = expectedType->getPointerTo(); - if (val->getType() != expectedType) { - llvm::Type *t = - llvm::cast(val->getType())->getElementType(); - assert(getTypeStoreSize(DtoType(type)) <= getTypeStoreSize(t) && - "Global type mismatch, encountered type too small."); - val = DtoBitCast(val, expectedType); - } + if (val->getType() != expectedType) { + // The type of globals is determined by their initializer, and the front-end + // may inject implicit casts for class references and static arrays. + assert(vd->isDataseg() || (vd->storage_class & STCextern) || + type->toBasetype()->ty == Tclass || type->toBasetype()->ty == Tsarray); + llvm::Type *pointeeType = val->getType()->getPointerElementType(); + if (isSpecialRef) + pointeeType = pointeeType->getPointerElementType(); + // Make sure that the type sizes fit - '==' instead of '<=' should probably + // work as well. + assert(getTypeStoreSize(DtoType(type)) <= getTypeStoreSize(pointeeType) && + "LValue type mismatch, encountered type too small."); + val = DtoBitCast(val, expectedType); } - if (isSpecialRefVar(vd)) + if (isSpecialRef) return new DSpecialRefValue(type, val); return new DLValue(type, val); diff --git a/gen/tocall.cpp b/gen/tocall.cpp index dc39ca7544..bc6245f2d6 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -596,7 +596,7 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e, Expression *exp1 = (*e->arguments)[0]; LLValue *ptr = DtoRVal(exp1); - result = new DImValue(exp1->type, DtoVolatileLoad(ptr)); + result = new DImValue(e->type, DtoVolatileLoad(ptr)); return true; } @@ -849,7 +849,7 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval, arguments ? arguments->dim : 0; // number of explicit arguments std::vector argvals(n_arguments, static_cast(nullptr)); - if (dfnval && dfnval->func->isArrayOp) { + if (dfnval && dfnval->func && dfnval->func->isArrayOp) { // For array ops, the druntime implementation signatures are crafted // specifically such that the evaluation order is as expected with // the strange DMD reverse parameter passing order. Thus, we need diff --git a/gen/toir.cpp b/gen/toir.cpp index bf4e4759d1..6f996ca12e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -850,8 +850,7 @@ public: // handle cast to void (usually created by frontend to avoid "has no effect" // error) if (e->to == Type::tvoid) { - result = new DConstValue(Type::tvoid, - llvm::UndefValue::get(DtoMemType(Type::tvoid))); + result = nullptr; return; } @@ -892,29 +891,28 @@ public: assert(isaPointer(baseValue)); llvm::Value *offsetValue; - Type *offsetType; if (e->offset == 0) { offsetValue = baseValue; - offsetType = base->type->pointerTo(); } else { uint64_t elemSize = gDataLayout->getTypeAllocSize( baseValue->getType()->getContainedType(0)); if (e->offset % elemSize == 0) { // We can turn this into a "nice" GEP. offsetValue = DtoGEPi1(baseValue, e->offset / elemSize); - offsetType = base->type->pointerTo(); } else { // Offset isn't a multiple of base type size, just cast to i8* and // apply the byte offset. offsetValue = DtoGEPi1(DtoBitCast(baseValue, getVoidPtrType()), e->offset); - offsetType = Type::tvoidptr; } } // Casts are also "optimized into" SymOffExp by the frontend. - result = DtoCast(e->loc, new DImValue(offsetType, offsetValue), e->type); + LLValue *llVal = (e->type->toBasetype()->isintegral() + ? p->ir->CreatePtrToInt(offsetValue, DtoType(e->type)) + : DtoBitCast(offsetValue, DtoType(e->type))); + result = new DImValue(e->type, llVal); } ////////////////////////////////////////////////////////////////////////////// @@ -984,10 +982,11 @@ public: if (e->type->toBasetype()->ty == Tfunction) { assert(!e->cachedLvalue); DValue *dv = toElem(e->e1); + LLValue *llVal = DtoRVal(dv); if (DFuncValue *dfv = dv->isFunc()) { - result = new DFuncValue(e->type, dfv->func, DtoRVal(dfv)); + result = new DFuncValue(e->type, dfv->func, llVal); } else { - result = new DImValue(e->type, DtoRVal(dv)); + result = new DImValue(e->type, llVal); } return; } @@ -1000,26 +999,7 @@ public: V = DtoRVal(e->e1); } - // The frontend emits dereferences of class/interfaces types to access the - // first member, which is the .classinfo property. - Type *origType = e->e1->type->toBasetype(); - if (origType->ty == Tclass) { - TypeClass *ct = static_cast(origType); - - Type *resultType; - if (ct->sym->isInterfaceDeclaration()) { - // For interfaces, the first entry in the vtbl is actually a pointer - // to an Interface instance, which has the type info as its first - // member, so we have to add an extra layer of indirection. - resultType = Type::typeinfointerface->type->pointerTo(); - } else { - resultType = Type::typeinfoclass->type; - } - - V = DtoBitCast(V, DtoType(resultType->pointerTo()->pointerTo())); - } - - result = new DLValue(e->type, V); + result = new DLValue(e->type, DtoBitCast(V, DtoPtrToType(e->type))); } ////////////////////////////////////////////////////////////////////////////// @@ -1071,7 +1051,7 @@ public: } // Logger::cout() << "mem: " << *arrptr << '\n'; - result = new DLValue(e->type, arrptr); + result = new DLValue(e->type, DtoBitCast(arrptr, DtoPtrToType(e->type))); } else if (FuncDeclaration *fdecl = e->var->isFuncDeclaration()) { DtoResolveFunction(fdecl); @@ -1135,7 +1115,7 @@ public: Logger::println("normal this exp"); v = p->func()->thisArg; } - result = new DLValue(e->type, v); + result = new DLValue(e->type, DtoBitCast(v, DtoPtrToType(e->type))); } ////////////////////////////////////////////////////////////////////////////// @@ -1183,7 +1163,7 @@ public: IF_LOG Logger::println("e1type: %s", e1type->toChars()); llvm_unreachable("Unknown IndexExp target."); } - result = new DLValue(e->type, arrptr); + result = new DLValue(e->type, DtoBitCast(arrptr, DtoPtrToType(e->type))); } ////////////////////////////////////////////////////////////////////////////// @@ -1284,15 +1264,17 @@ public: // The frontend generates a SliceExp of static array type when assigning a // fixed-width slice to a static array. - if (e->type->toBasetype()->ty == Tsarray) { - LLValue *v = DtoBitCast(eptr, DtoType(e->type->pointerTo())); - result = new DLValue(e->type, v); + Type *const ety = e->type->toBasetype(); + if (ety->ty == Tsarray) { + result = new DLValue(e->type, DtoBitCast(eptr, DtoPtrToType(e->type))); return; } - if (!elen) { + assert(ety->ty == Tarray); + if (!elen) elen = DtoArrayLen(v); - } + eptr = DtoBitCast(eptr, DtoPtrToType(ety->nextOf())); + result = new DSliceValue(e->type, elen, eptr); } @@ -1747,13 +1729,8 @@ public: auto &PGO = gIR->func()->pgo; PGO.setCurrentStmt(e); - // DMD allows syntax like this: - // f() == 0 || assert(false) - result = new DImValue(e->type, DtoConstBool(false)); - - if (!global.params.useAssert) { + if (!global.params.useAssert) return; - } // condition DValue *cond; @@ -1885,6 +1862,11 @@ public: llvm::BranchInst::Create(andandend, p->scopebb()); p->scope() = IRScope(andandend); + if (e->type->toBasetype()->ty == Tvoid) { + result = nullptr; + return; + } + LLValue *resval = nullptr; if (ubool == vbool || !vbool) { // No need to create a PHI node. @@ -1941,6 +1923,11 @@ public: llvm::BranchInst::Create(ororend, p->scopebb()); p->scope() = IRScope(ororend); + if (e->type->toBasetype()->ty == Tvoid) { + result = nullptr; + return; + } + LLValue *resval = nullptr; if (ubool == vbool || !vbool) { // No need to create a PHI node. @@ -2181,11 +2168,8 @@ public: llvm::BranchInst::Create(condend, p->scopebb()); p->scope() = IRScope(condend); - if (retPtr) { + if (retPtr) result = new DSpecialRefValue(e->type, retPtr); - } else { - result = new DConstValue(e->type, getNullValue(DtoMemType(dtype))); - } } //////////////////////////////////////////////////////////////////////////////