Skip to content

Commit

Permalink
Continue with DValue refactoring
Browse files Browse the repository at this point in the history
* Introduce a DRValue base class to be able to discriminate between
  DLValues and DRValues (e.g., function parameters).
* Let DValue::getRVal() return each DValue's value as DRValue.
  This allows to convert a DLValue to a DRValue while retaining the D
  type, something we've previously lost when returning the low-level
  rvalue directly.
* Let the DtoR/LVal() helpers be the only way to convert a DValue to a
  low-level value.
  • Loading branch information
kinke committed Jun 15, 2016
1 parent 235f392 commit c91e94f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 77 deletions.
46 changes: 30 additions & 16 deletions gen/dvalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,31 @@ bool isDefinedInFuncEntryBB(LLValue *v) {

////////////////////////////////////////////////////////////////////////////////

LLValue *DtoLVal(DValue *v) {
auto lval = v->isLVal();
assert(lval);
return lval->getLVal()->val;
}

////////////////////////////////////////////////////////////////////////////////

DValue::DValue(Type *t, LLValue *v) : type(t), val(v) {
assert(type);
assert(val);
}

bool DValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }

////////////////////////////////////////////////////////////////////////////////

DImValue::DImValue(Type *t, llvm::Value *v) : DValue(t, v) {
DRValue::DRValue(Type *t, LLValue *v) : DValue(t, v) {
assert(!DtoIsInMemoryOnly(t) &&
"Cannot represent memory-only type as immediate DValue");
"Cannot represent memory-only type as DRValue");
}

////////////////////////////////////////////////////////////////////////////////

DConstValue::DConstValue(Type *t, llvm::Constant *con) : DValue(t, con) {}
DConstValue::DConstValue(Type *t, LLConstant *con) : DRValue(t, con) {}

////////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -78,18 +91,19 @@ DLValue::DLValue(Type *t, LLValue *v) : DValue(t, v) {
assert(checkVarValueType(v->getType(), false));
}

LLValue *DLValue::getRVal() {
DRValue *DLValue::getRVal() {
if (DtoIsInMemoryOnly(type->toBasetype())) {
llvm_unreachable("getRVal() for memory-only type");
return nullptr;
}

LLValue *rawValue = DtoLoad(val);
if (type->toBasetype()->ty != Tbool)
return rawValue;
LLValue *rval = DtoLoad(val);
if (type->toBasetype()->ty == Tbool) {
assert(rval->getType() == llvm::Type::getInt8Ty(gIR->context()));
rval = gIR->ir->CreateTrunc(rval, llvm::Type::getInt1Ty(gIR->context()));
}

assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
return gIR->ir->CreateTrunc(rawValue, llvm::Type::getInt1Ty(gIR->context()));
return new DImValue(type, rval);
}

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -98,16 +112,16 @@ 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();
DRValue *DSpecialRefValue::getRVal() {
return DLValue(type, DtoLoad(val)).getRVal();
}

DLValue *DSpecialRefValue::getLVal() { return new DLValue(type, DtoLoad(val)); }

////////////////////////////////////////////////////////////////////////////////

DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr)
: DValue(t, DtoAggrPair(length, ptr)) {}
: DRValue(t, DtoAggrPair(length, ptr)) {}

LLValue *DSliceValue::getLength() { return DtoExtractValue(val, 0, ".len"); }

Expand All @@ -116,10 +130,10 @@ LLValue *DSliceValue::getPtr() { return DtoExtractValue(val, 1, ".ptr"); }
////////////////////////////////////////////////////////////////////////////////

DFuncValue::DFuncValue(Type *t, FuncDeclaration *fd, LLValue *v, LLValue *vt)
: DValue(t, v), func(fd), vthis(vt) {}
: DRValue(t, v), func(fd), vthis(vt) {}

DFuncValue::DFuncValue(FuncDeclaration *fd, LLValue *v, LLValue *vt)
: DValue(fd->type, v), func(fd), vthis(vt) {}
: DRValue(fd->type, v), func(fd), vthis(vt) {}

bool DFuncValue::definedInFuncEntryBB() {
return isDefinedInFuncEntryBB(val) &&
Expand Down
110 changes: 64 additions & 46 deletions gen/dvalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#define LDC_GEN_DVALUE_H

#include "root.h"
#include <cassert>

class Type;
class Dsymbol;
Expand All @@ -31,35 +30,38 @@ class Type;
class Constant;
}

class DValue;
class DRValue;
class DImValue;
class DConstValue;
class DNullValue;
class DLValue;
class DSpecialRefValue;
class DFuncValue;
class DSliceValue;
class DFuncValue;

// base class for d-values
/// Associates an immutable low-level value with an immutable D type.
class DValue {
public:
Type *const type;

virtual ~DValue() = default;

virtual llvm::Value *getRVal() { return val; }

/// Returns true iff the value can be accessed at the end of the entry basic
/// block of the current function, in the sense that it is either not derived
/// from an llvm::Instruction (but from a global, constant, etc.) or that
/// instruction is part of the entry basic block.
///
/// In other words, whatever value the result of getLVal()/getRVal() might be
/// derived from then certainly dominates uses in all other basic blocks of
/// the function.
/// In other words, whatever the value might be derived from from then
/// certainly dominates uses in all other basic blocks of the function.
virtual bool definedInFuncEntryBB();

virtual DRValue *getRVal() { return nullptr; }

virtual DLValue *isLVal() { return nullptr; }
virtual DSpecialRefValue *isSpecialRef() { return nullptr; }

virtual DRValue *isRVal() { return nullptr; }
virtual DImValue *isIm() { return nullptr; }
virtual DConstValue *isConst() { return nullptr; }
virtual DNullValue *isNull() { return nullptr; }
Expand All @@ -69,22 +71,32 @@ class DValue {
protected:
llvm::Value *const val;

DValue(Type *t, llvm::Value *v) : type(t), val(v) {
assert(type);
assert(val);
}
DValue(Type *t, llvm::Value *v);

friend llvm::Value *DtoRVal(DValue *v);
};

/// Represents a D rvalue via a low-level rvalue.
class DRValue : public DValue {
public:
DRValue *getRVal() override { return this; }

DRValue *isRVal() override { return this; }

protected:
DRValue(Type *t, llvm::Value *v);
};

// immediate d-value
class DImValue : public DValue {
/// Represents an immediate D value via a low-level rvalue.
class DImValue : public DRValue {
public:
DImValue(Type *t, llvm::Value *v);
DImValue(Type *t, llvm::Value *v) : DRValue(t, v) {}

DImValue *isIm() override { return this; }
};

// constant d-value
class DConstValue : public DValue {
/// Represents a constant D value via a low-level constant.
class DConstValue : public DRValue {
public:
DConstValue(Type *t, llvm::Constant *con);

Expand All @@ -93,66 +105,72 @@ class DConstValue : public DValue {
DConstValue *isConst() override { return this; }
};

// null d-value
/// Represents a D null constant.
class DNullValue : public DConstValue {
public:
DNullValue(Type *t, llvm::Constant *con) : DConstValue(t, con) {}

DNullValue *isNull() override { return this; }
};

/// Represents a D slice (dynamic array).
class DSliceValue : public DRValue {
public:
DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr);

DSliceValue *isSlice() override { return this; }

llvm::Value *getLength();
llvm::Value *getPtr();
};

/// Represents a D function value with optional this/context pointer.
class DFuncValue : public DRValue {
public:
FuncDeclaration *func;
llvm::Value *vthis;

DFuncValue(Type *t, FuncDeclaration *fd, llvm::Value *v,
llvm::Value *vt = nullptr);
DFuncValue(FuncDeclaration *fd, llvm::Value *v, llvm::Value *vt = nullptr);

bool definedInFuncEntryBB() override;

DFuncValue *isFunc() override { return this; }
};

/// 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.
class DLValue : public DValue {
public:
DLValue(Type *t, llvm::Value *v);

virtual llvm::Value *getLVal() { return val; }
llvm::Value *getRVal() override;
DRValue *getRVal() override;
virtual DLValue *getLVal() { return this; }

DLValue *isLVal() override { return this; }

protected:
DLValue(llvm::Value *v, Type *t) : DValue(t, v) {}

friend llvm::Value *DtoLVal(DValue *v);
};

/// Represents special internal ref variables.
class DSpecialRefValue : public DLValue {
public:
DSpecialRefValue(Type *t, llvm::Value *v);

DRValue *getRVal() override;
DLValue *getLVal() override;
llvm::Value *getRefStorage() { return val; }
llvm::Value *getLVal() override;
llvm::Value *getRVal() override;

DSpecialRefValue *isSpecialRef() override { return this; }
};

// slice d-value
class DSliceValue : public DValue {
public:
DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr);

DSliceValue *isSlice() override { return this; }

llvm::Value *getLength();
llvm::Value *getPtr();
};

// function d-value
class DFuncValue : public DValue {
public:
FuncDeclaration *func;
llvm::Value *vthis;

DFuncValue(Type *t, FuncDeclaration *fd, llvm::Value *v,
llvm::Value *vt = nullptr);
DFuncValue(FuncDeclaration *fd, llvm::Value *v, llvm::Value *vt = nullptr);

bool definedInFuncEntryBB() override;

DFuncValue *isFunc() override { return this; }
};
inline llvm::Value *DtoRVal(DValue *v) { return v->getRVal()->val; }
llvm::Value *DtoLVal(DValue *v);

#endif // LDC_GEN_DVALUE_H
10 changes: 0 additions & 10 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1869,13 +1869,3 @@ DValue *makeVarDValue(Type *type, VarDeclaration *vd, llvm::Value *storage) {

return new DLValue(type, val);
}

LLValue *DtoRVal(DValue *v) { return v->getRVal(); }
LLValue *DtoLVal(DValue *v) {
auto lval = v->isLVal();
assert(lval);
return lval->getLVal();
}

LLValue *DtoRVal(Expression *e) { return DtoRVal(toElem(e)); }
LLValue *DtoLVal(Expression *e) { return DtoLVal(toElem(e)); }
6 changes: 2 additions & 4 deletions gen/llvmhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,8 @@ DValue *toElem(Expression *e, bool tryGetLvalue);
DValue *toElemDtor(Expression *e);
LLConstant *toConstElem(Expression *e, IRState *p);

llvm::Value *DtoRVal(DValue *v);
llvm::Value *DtoRVal(Expression *e);
llvm::Value *DtoLVal(DValue *v);
llvm::Value *DtoLVal(Expression *e);
inline llvm::Value *DtoRVal(Expression *e) { return DtoRVal(toElem(e)); }
inline llvm::Value *DtoLVal(Expression *e) { return DtoLVal(toElem(e)); }

/// Creates a DLValue for the given VarDeclaration.
///
Expand Down
2 changes: 1 addition & 1 deletion gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
DtoAssign(loc, &field, val, TOKconstruct, true);

if (expr && expr->isLvalue()) {
callPostblit(loc, expr, field.getLVal());
callPostblit(loc, expr, DtoLVal(&field));
}

// Also zero out padding bytes counted as being part of the type in DMD
Expand Down

0 comments on commit c91e94f

Please sign in to comment.