mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
Enforce type consistency for most DValues
At the cost of some more bitcasts.
This commit is contained in:
parent
88b19d3d51
commit
d6dcc7a4db
7 changed files with 78 additions and 99 deletions
|
@ -590,11 +590,11 @@ void initializeArrayLiteral(IRState *p, ArrayLiteralExp *ale, LLValue *dstMem) {
|
||||||
} else {
|
} else {
|
||||||
// Store the elements one by one.
|
// Store the elements one by one.
|
||||||
for (size_t i = 0; i < elemCount; ++i) {
|
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());
|
LLValue *lhsPtr = DtoGEPi(dstMem, 0, i, "", p->scopebb());
|
||||||
auto vv = new DLValue(e->type, elemAddr);
|
DLValue lhs(rhs->type, DtoBitCast(lhsPtr, DtoPtrToType(rhs->type)));
|
||||||
DtoAssign(ale->loc, vv, e, TOKconstruct, true);
|
DtoAssign(ale->loc, &lhs, rhs, TOKconstruct, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,8 +261,8 @@ DValue *binBitwise(Loc &loc, Type *type, Expression *lhs, Expression *rhs,
|
||||||
bool loadLhsAfterRhs) {
|
bool loadLhsAfterRhs) {
|
||||||
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
|
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
|
||||||
|
|
||||||
LLValue *l = DtoRVal(rvals.lhs);
|
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
|
||||||
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, lhs->type));
|
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
|
||||||
LLValue *res = llvm::BinaryOperator::Create(binOp, l, r, "", gIR->scopebb());
|
LLValue *res = llvm::BinaryOperator::Create(binOp, l, r, "", gIR->scopebb());
|
||||||
|
|
||||||
return new DImValue(type, res);
|
return new DImValue(type, res);
|
||||||
|
|
|
@ -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)
|
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"); }
|
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) {}
|
: DRValue(t, v), func(fd), vthis(vt) {}
|
||||||
|
|
||||||
DFuncValue::DFuncValue(FuncDeclaration *fd, LLValue *v, LLValue *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() {
|
bool DFuncValue::definedInFuncEntryBB() {
|
||||||
return isDefinedInFuncEntryBB(val) &&
|
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<llvm::PointerType>(t);
|
|
||||||
if (!pt) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = pt->getElementType();
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::PointerType *pt = llvm::dyn_cast<llvm::PointerType>(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) {
|
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() {
|
DRValue *DLValue::getRVal() {
|
||||||
|
@ -131,7 +120,7 @@ DRValue *DLValue::getRVal() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
|
DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
|
||||||
assert(checkVarValueType(v->getType(), true));
|
assert(v->getType() == DtoPtrToType(t)->getPointerTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
DRValue *DSpecialRefValue::getRVal() {
|
DRValue *DSpecialRefValue::getRVal() {
|
||||||
|
|
|
@ -93,7 +93,7 @@ protected:
|
||||||
/// integral and floating-point types.
|
/// integral and floating-point types.
|
||||||
class DImValue : public DRValue {
|
class DImValue : public DRValue {
|
||||||
public:
|
public:
|
||||||
DImValue(Type *t, llvm::Value *v) : DRValue(t, v) {}
|
DImValue(Type *t, llvm::Value *v);
|
||||||
|
|
||||||
DImValue *isIm() override { return this; }
|
DImValue *isIm() override { return this; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -396,7 +396,7 @@ DValue *DtoNullValue(Type *type, Loc loc) {
|
||||||
// representation
|
// representation
|
||||||
if (basetype->isintegral() || basetype->isfloating() || basety == Tpointer ||
|
if (basetype->isintegral() || basetype->isfloating() || basety == Tpointer ||
|
||||||
basety == Tclass || basety == Tdelegate || basety == Taarray) {
|
basety == Tclass || basety == Tdelegate || basety == Taarray) {
|
||||||
return new DConstValue(type, LLConstant::getNullValue(lltype));
|
return new DNullValue(type, LLConstant::getNullValue(lltype));
|
||||||
}
|
}
|
||||||
// dynamic array
|
// dynamic array
|
||||||
if (basety == Tarray) {
|
if (basety == Tarray) {
|
||||||
|
@ -1553,7 +1553,7 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
|
||||||
assert(!isSpecialRefVar(vd) && "Code not expected to handle special "
|
assert(!isSpecialRefVar(vd) && "Code not expected to handle special "
|
||||||
"ref vars, although it can easily be "
|
"ref vars, although it can easily be "
|
||||||
"made to.");
|
"made to.");
|
||||||
return new DLValue(type, getIrValue(vd));
|
return new DLValue(type, DtoBitCast(getIrValue(vd), DtoPtrToType(type)));
|
||||||
} else {
|
} else {
|
||||||
Logger::println("a normal variable");
|
Logger::println("a normal variable");
|
||||||
|
|
||||||
|
@ -1806,22 +1806,28 @@ DValue *makeVarDValue(Type *type, VarDeclaration *vd, llvm::Value *storage) {
|
||||||
val = getIrValue(vd);
|
val = getIrValue(vd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd->isDataseg() || (vd->storage_class & STCextern)) {
|
// We might need to cast.
|
||||||
// The type of globals is determined by their initializer, so
|
llvm::Type *expectedType = DtoPtrToType(type);
|
||||||
// we might need to cast. Make sure that the type sizes fit -
|
const bool isSpecialRef = isSpecialRefVar(vd);
|
||||||
// '==' instead of '<=' should probably work as well.
|
if (isSpecialRef)
|
||||||
llvm::Type *expectedType = llvm::PointerType::getUnqual(DtoMemType(type));
|
expectedType = expectedType->getPointerTo();
|
||||||
|
|
||||||
if (val->getType() != expectedType) {
|
if (val->getType() != expectedType) {
|
||||||
llvm::Type *t =
|
// The type of globals is determined by their initializer, and the front-end
|
||||||
llvm::cast<llvm::PointerType>(val->getType())->getElementType();
|
// may inject implicit casts for class references and static arrays.
|
||||||
assert(getTypeStoreSize(DtoType(type)) <= getTypeStoreSize(t) &&
|
assert(vd->isDataseg() || (vd->storage_class & STCextern) ||
|
||||||
"Global type mismatch, encountered type too small.");
|
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);
|
val = DtoBitCast(val, expectedType);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (isSpecialRefVar(vd))
|
if (isSpecialRef)
|
||||||
return new DSpecialRefValue(type, val);
|
return new DSpecialRefValue(type, val);
|
||||||
|
|
||||||
return new DLValue(type, val);
|
return new DLValue(type, val);
|
||||||
|
|
|
@ -596,7 +596,7 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
|
|
||||||
Expression *exp1 = (*e->arguments)[0];
|
Expression *exp1 = (*e->arguments)[0];
|
||||||
LLValue *ptr = DtoRVal(exp1);
|
LLValue *ptr = DtoRVal(exp1);
|
||||||
result = new DImValue(exp1->type, DtoVolatileLoad(ptr));
|
result = new DImValue(e->type, DtoVolatileLoad(ptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +849,7 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval,
|
||||||
arguments ? arguments->dim : 0; // number of explicit arguments
|
arguments ? arguments->dim : 0; // number of explicit arguments
|
||||||
|
|
||||||
std::vector<DValue *> argvals(n_arguments, static_cast<DValue *>(nullptr));
|
std::vector<DValue *> argvals(n_arguments, static_cast<DValue *>(nullptr));
|
||||||
if (dfnval && dfnval->func->isArrayOp) {
|
if (dfnval && dfnval->func && dfnval->func->isArrayOp) {
|
||||||
// For array ops, the druntime implementation signatures are crafted
|
// For array ops, the druntime implementation signatures are crafted
|
||||||
// specifically such that the evaluation order is as expected with
|
// specifically such that the evaluation order is as expected with
|
||||||
// the strange DMD reverse parameter passing order. Thus, we need
|
// the strange DMD reverse parameter passing order. Thus, we need
|
||||||
|
|
78
gen/toir.cpp
78
gen/toir.cpp
|
@ -850,8 +850,7 @@ public:
|
||||||
// handle cast to void (usually created by frontend to avoid "has no effect"
|
// handle cast to void (usually created by frontend to avoid "has no effect"
|
||||||
// error)
|
// error)
|
||||||
if (e->to == Type::tvoid) {
|
if (e->to == Type::tvoid) {
|
||||||
result = new DConstValue(Type::tvoid,
|
result = nullptr;
|
||||||
llvm::UndefValue::get(DtoMemType(Type::tvoid)));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,29 +891,28 @@ public:
|
||||||
assert(isaPointer(baseValue));
|
assert(isaPointer(baseValue));
|
||||||
|
|
||||||
llvm::Value *offsetValue;
|
llvm::Value *offsetValue;
|
||||||
Type *offsetType;
|
|
||||||
|
|
||||||
if (e->offset == 0) {
|
if (e->offset == 0) {
|
||||||
offsetValue = baseValue;
|
offsetValue = baseValue;
|
||||||
offsetType = base->type->pointerTo();
|
|
||||||
} else {
|
} else {
|
||||||
uint64_t elemSize = gDataLayout->getTypeAllocSize(
|
uint64_t elemSize = gDataLayout->getTypeAllocSize(
|
||||||
baseValue->getType()->getContainedType(0));
|
baseValue->getType()->getContainedType(0));
|
||||||
if (e->offset % elemSize == 0) {
|
if (e->offset % elemSize == 0) {
|
||||||
// We can turn this into a "nice" GEP.
|
// We can turn this into a "nice" GEP.
|
||||||
offsetValue = DtoGEPi1(baseValue, e->offset / elemSize);
|
offsetValue = DtoGEPi1(baseValue, e->offset / elemSize);
|
||||||
offsetType = base->type->pointerTo();
|
|
||||||
} else {
|
} else {
|
||||||
// Offset isn't a multiple of base type size, just cast to i8* and
|
// Offset isn't a multiple of base type size, just cast to i8* and
|
||||||
// apply the byte offset.
|
// apply the byte offset.
|
||||||
offsetValue =
|
offsetValue =
|
||||||
DtoGEPi1(DtoBitCast(baseValue, getVoidPtrType()), e->offset);
|
DtoGEPi1(DtoBitCast(baseValue, getVoidPtrType()), e->offset);
|
||||||
offsetType = Type::tvoidptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Casts are also "optimized into" SymOffExp by the frontend.
|
// 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) {
|
if (e->type->toBasetype()->ty == Tfunction) {
|
||||||
assert(!e->cachedLvalue);
|
assert(!e->cachedLvalue);
|
||||||
DValue *dv = toElem(e->e1);
|
DValue *dv = toElem(e->e1);
|
||||||
|
LLValue *llVal = DtoRVal(dv);
|
||||||
if (DFuncValue *dfv = dv->isFunc()) {
|
if (DFuncValue *dfv = dv->isFunc()) {
|
||||||
result = new DFuncValue(e->type, dfv->func, DtoRVal(dfv));
|
result = new DFuncValue(e->type, dfv->func, llVal);
|
||||||
} else {
|
} else {
|
||||||
result = new DImValue(e->type, DtoRVal(dv));
|
result = new DImValue(e->type, llVal);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1000,26 +999,7 @@ public:
|
||||||
V = DtoRVal(e->e1);
|
V = DtoRVal(e->e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The frontend emits dereferences of class/interfaces types to access the
|
result = new DLValue(e->type, DtoBitCast(V, DtoPtrToType(e->type)));
|
||||||
// first member, which is the .classinfo property.
|
|
||||||
Type *origType = e->e1->type->toBasetype();
|
|
||||||
if (origType->ty == Tclass) {
|
|
||||||
TypeClass *ct = static_cast<TypeClass *>(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1071,7 +1051,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger::cout() << "mem: " << *arrptr << '\n';
|
// 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()) {
|
} else if (FuncDeclaration *fdecl = e->var->isFuncDeclaration()) {
|
||||||
DtoResolveFunction(fdecl);
|
DtoResolveFunction(fdecl);
|
||||||
|
|
||||||
|
@ -1135,7 +1115,7 @@ public:
|
||||||
Logger::println("normal this exp");
|
Logger::println("normal this exp");
|
||||||
v = p->func()->thisArg;
|
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());
|
IF_LOG Logger::println("e1type: %s", e1type->toChars());
|
||||||
llvm_unreachable("Unknown IndexExp target.");
|
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
|
// The frontend generates a SliceExp of static array type when assigning a
|
||||||
// fixed-width slice to a static array.
|
// fixed-width slice to a static array.
|
||||||
if (e->type->toBasetype()->ty == Tsarray) {
|
Type *const ety = e->type->toBasetype();
|
||||||
LLValue *v = DtoBitCast(eptr, DtoType(e->type->pointerTo()));
|
if (ety->ty == Tsarray) {
|
||||||
result = new DLValue(e->type, v);
|
result = new DLValue(e->type, DtoBitCast(eptr, DtoPtrToType(e->type)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elen) {
|
assert(ety->ty == Tarray);
|
||||||
|
if (!elen)
|
||||||
elen = DtoArrayLen(v);
|
elen = DtoArrayLen(v);
|
||||||
}
|
eptr = DtoBitCast(eptr, DtoPtrToType(ety->nextOf()));
|
||||||
|
|
||||||
result = new DSliceValue(e->type, elen, eptr);
|
result = new DSliceValue(e->type, elen, eptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1747,13 +1729,8 @@ public:
|
||||||
auto &PGO = gIR->func()->pgo;
|
auto &PGO = gIR->func()->pgo;
|
||||||
PGO.setCurrentStmt(e);
|
PGO.setCurrentStmt(e);
|
||||||
|
|
||||||
// DMD allows syntax like this:
|
if (!global.params.useAssert)
|
||||||
// f() == 0 || assert(false)
|
|
||||||
result = new DImValue(e->type, DtoConstBool(false));
|
|
||||||
|
|
||||||
if (!global.params.useAssert) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// condition
|
// condition
|
||||||
DValue *cond;
|
DValue *cond;
|
||||||
|
@ -1885,6 +1862,11 @@ public:
|
||||||
llvm::BranchInst::Create(andandend, p->scopebb());
|
llvm::BranchInst::Create(andandend, p->scopebb());
|
||||||
p->scope() = IRScope(andandend);
|
p->scope() = IRScope(andandend);
|
||||||
|
|
||||||
|
if (e->type->toBasetype()->ty == Tvoid) {
|
||||||
|
result = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LLValue *resval = nullptr;
|
LLValue *resval = nullptr;
|
||||||
if (ubool == vbool || !vbool) {
|
if (ubool == vbool || !vbool) {
|
||||||
// No need to create a PHI node.
|
// No need to create a PHI node.
|
||||||
|
@ -1941,6 +1923,11 @@ public:
|
||||||
llvm::BranchInst::Create(ororend, p->scopebb());
|
llvm::BranchInst::Create(ororend, p->scopebb());
|
||||||
p->scope() = IRScope(ororend);
|
p->scope() = IRScope(ororend);
|
||||||
|
|
||||||
|
if (e->type->toBasetype()->ty == Tvoid) {
|
||||||
|
result = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LLValue *resval = nullptr;
|
LLValue *resval = nullptr;
|
||||||
if (ubool == vbool || !vbool) {
|
if (ubool == vbool || !vbool) {
|
||||||
// No need to create a PHI node.
|
// No need to create a PHI node.
|
||||||
|
@ -2181,11 +2168,8 @@ public:
|
||||||
llvm::BranchInst::Create(condend, p->scopebb());
|
llvm::BranchInst::Create(condend, p->scopebb());
|
||||||
|
|
||||||
p->scope() = IRScope(condend);
|
p->scope() = IRScope(condend);
|
||||||
if (retPtr) {
|
if (retPtr)
|
||||||
result = new DSpecialRefValue(e->type, retPtr);
|
result = new DSpecialRefValue(e->type, retPtr);
|
||||||
} else {
|
|
||||||
result = new DConstValue(e->type, getNullValue(DtoMemType(dtype)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue