Handle internal ref variables in class DSpecialRefValue

This commit is contained in:
Martin 2016-06-08 23:58:08 +02:00
parent de9149f1b6
commit f70f11fac5
4 changed files with 40 additions and 32 deletions

View file

@ -74,38 +74,34 @@ static bool checkVarValueType(LLType *t, bool extraDeref) {
return true;
}
DLValue::DLValue(Type *t, LLValue *v, bool isSpecialRefVar)
: DValue(t, v), isSpecialRefVar(isSpecialRefVar) {
assert(v && "Unexpected null llvm::Value.");
assert(checkVarValueType(v->getType(), isSpecialRefVar));
DLValue::DLValue(Type *t, LLValue *v) : DValue(t, v) {
assert(checkVarValueType(v->getType(), false));
}
LLValue *DLValue::getLVal() { return isSpecialRefVar ? DtoLoad(val) : val; }
LLValue *DLValue::getRVal() {
LLValue *storage = val;
if (isSpecialRefVar)
storage = DtoLoad(storage);
if (DtoIsInMemoryOnly(type->toBasetype())) {
llvm_unreachable("getRVal() for memory-only type");
return nullptr;
}
LLValue *rawValue = DtoLoad(storage);
if (type->toBasetype()->ty == Tbool) {
assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
return gIR->ir->CreateTrunc(rawValue,
llvm::Type::getInt1Ty(gIR->context()));
}
LLValue *rawValue = DtoLoad(val);
if (type->toBasetype()->ty != Tbool)
return rawValue;
assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
return gIR->ir->CreateTrunc(rawValue, llvm::Type::getInt1Ty(gIR->context()));
}
LLValue *DLValue::getRefStorage() {
assert(isSpecialRefVar);
return val;
////////////////////////////////////////////////////////////////////////////////
DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
assert(checkVarValueType(v->getType(), true));
}
LLValue *DSpecialRefValue::getLVal() { return DtoLoad(val); }
LLValue *DSpecialRefValue::getRVal() {
return DLValue(type, getLVal()).getRVal();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -35,6 +35,7 @@ class DImValue;
class DConstValue;
class DNullValue;
class DLValue;
class DSpecialRefValue;
class DFuncValue;
class DSliceValue;
@ -58,6 +59,7 @@ public:
virtual bool definedInFuncEntryBB();
virtual DLValue *isLVal() { return nullptr; }
virtual DSpecialRefValue *isSpecialRef() { return nullptr; }
virtual DImValue *isIm() { return nullptr; }
virtual DConstValue *isConst() { return nullptr; }
virtual DNullValue *isNull() { return nullptr; }
@ -102,22 +104,29 @@ public:
/// Represents a D value in memory via a low-level lvalue.
/// This doesn't imply that the D value is an lvalue too - e.g., we always
/// keep structs and static arrays in memory.
// TODO: The isSpecialRefVar case should probably be its own subclass.
class DLValue : public DValue {
public:
DLValue(Type *t, llvm::Value *v, bool isSpecialRefVar = false);
DLValue(Type *t, llvm::Value *v);
virtual llvm::Value *getLVal();
virtual llvm::Value *getLVal() { return val; }
llvm::Value *getRVal() override;
/// Returns the underlying storage for special internal ref variables.
/// Illegal to call on any other value.
llvm::Value *getRefStorage();
DLValue *isLVal() override { return this; }
protected:
const bool isSpecialRefVar;
DLValue(llvm::Value *v, Type *t) : DValue(t, v) {}
};
/// Represents special internal ref variables.
class DSpecialRefValue : public DLValue {
public:
DSpecialRefValue(Type *t, llvm::Value *v);
llvm::Value *getRefStorage() { return val; }
llvm::Value *getLVal() override;
llvm::Value *getRVal() override;
DSpecialRefValue *isSpecialRef() override { return this; }
};
// slice d-value

View file

@ -1864,7 +1864,10 @@ DValue *makeVarDValue(Type *type, VarDeclaration *vd, llvm::Value *storage) {
}
}
return new DLValue(type, val, isSpecialRefVar(vd));
if (isSpecialRefVar(vd))
return new DSpecialRefValue(type, val);
return new DLValue(type, val);
}
LLValue *DtoRVal(DValue *v) { return v->getRVal(); }

View file

@ -535,7 +535,7 @@ public:
// Note that the variable value is accessed directly (instead
// of via getLVal(), which would perform a load from the
// uninitialized location), and that rhs is stored as an l-value!
DLValue *lhs = toElem(e->e1)->isLVal();
DSpecialRefValue *lhs = toElem(e->e1)->isSpecialRef();
assert(lhs);
result = toElem(e->e2);
@ -2291,7 +2291,7 @@ public:
p->scope() = IRScope(condend);
if (retPtr) {
result = new DLValue(e->type, retPtr, true);
result = new DSpecialRefValue(e->type, retPtr);
} else {
result = new DConstValue(e->type, getNullValue(DtoMemType(dtype)));
}