Skip to content

Commit c91e94f

Browse files
committed
Continue with DValue refactoring
* 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.
1 parent 235f392 commit c91e94f

File tree

5 files changed

+97
-77
lines changed

5 files changed

+97
-77
lines changed

gen/dvalue.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,31 @@ bool isDefinedInFuncEntryBB(LLValue *v) {
3636

3737
////////////////////////////////////////////////////////////////////////////////
3838

39+
LLValue *DtoLVal(DValue *v) {
40+
auto lval = v->isLVal();
41+
assert(lval);
42+
return lval->getLVal()->val;
43+
}
44+
45+
////////////////////////////////////////////////////////////////////////////////
46+
47+
DValue::DValue(Type *t, LLValue *v) : type(t), val(v) {
48+
assert(type);
49+
assert(val);
50+
}
51+
3952
bool DValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }
4053

4154
////////////////////////////////////////////////////////////////////////////////
4255

43-
DImValue::DImValue(Type *t, llvm::Value *v) : DValue(t, v) {
56+
DRValue::DRValue(Type *t, LLValue *v) : DValue(t, v) {
4457
assert(!DtoIsInMemoryOnly(t) &&
45-
"Cannot represent memory-only type as immediate DValue");
58+
"Cannot represent memory-only type as DRValue");
4659
}
4760

4861
////////////////////////////////////////////////////////////////////////////////
4962

50-
DConstValue::DConstValue(Type *t, llvm::Constant *con) : DValue(t, con) {}
63+
DConstValue::DConstValue(Type *t, LLConstant *con) : DRValue(t, con) {}
5164

5265
////////////////////////////////////////////////////////////////////////////////
5366

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

81-
LLValue *DLValue::getRVal() {
94+
DRValue *DLValue::getRVal() {
8295
if (DtoIsInMemoryOnly(type->toBasetype())) {
8396
llvm_unreachable("getRVal() for memory-only type");
8497
return nullptr;
8598
}
8699

87-
LLValue *rawValue = DtoLoad(val);
88-
if (type->toBasetype()->ty != Tbool)
89-
return rawValue;
100+
LLValue *rval = DtoLoad(val);
101+
if (type->toBasetype()->ty == Tbool) {
102+
assert(rval->getType() == llvm::Type::getInt8Ty(gIR->context()));
103+
rval = gIR->ir->CreateTrunc(rval, llvm::Type::getInt1Ty(gIR->context()));
104+
}
90105

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

95109
////////////////////////////////////////////////////////////////////////////////
@@ -98,16 +112,16 @@ DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
98112
assert(checkVarValueType(v->getType(), true));
99113
}
100114

101-
LLValue *DSpecialRefValue::getLVal() { return DtoLoad(val); }
102-
103-
LLValue *DSpecialRefValue::getRVal() {
104-
return DLValue(type, getLVal()).getRVal();
115+
DRValue *DSpecialRefValue::getRVal() {
116+
return DLValue(type, DtoLoad(val)).getRVal();
105117
}
106118

119+
DLValue *DSpecialRefValue::getLVal() { return new DLValue(type, DtoLoad(val)); }
120+
107121
////////////////////////////////////////////////////////////////////////////////
108122

109123
DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr)
110-
: DValue(t, DtoAggrPair(length, ptr)) {}
124+
: DRValue(t, DtoAggrPair(length, ptr)) {}
111125

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

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

118132
DFuncValue::DFuncValue(Type *t, FuncDeclaration *fd, LLValue *v, LLValue *vt)
119-
: DValue(t, v), func(fd), vthis(vt) {}
133+
: DRValue(t, v), func(fd), vthis(vt) {}
120134

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

124138
bool DFuncValue::definedInFuncEntryBB() {
125139
return isDefinedInFuncEntryBB(val) &&

gen/dvalue.h

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#define LDC_GEN_DVALUE_H
1919

2020
#include "root.h"
21-
#include <cassert>
2221

2322
class Type;
2423
class Dsymbol;
@@ -31,35 +30,38 @@ class Type;
3130
class Constant;
3231
}
3332

33+
class DValue;
34+
class DRValue;
3435
class DImValue;
3536
class DConstValue;
3637
class DNullValue;
3738
class DLValue;
3839
class DSpecialRefValue;
39-
class DFuncValue;
4040
class DSliceValue;
41+
class DFuncValue;
4142

42-
// base class for d-values
43+
/// Associates an immutable low-level value with an immutable D type.
4344
class DValue {
4445
public:
4546
Type *const type;
4647

4748
virtual ~DValue() = default;
4849

49-
virtual llvm::Value *getRVal() { return val; }
50-
5150
/// Returns true iff the value can be accessed at the end of the entry basic
5251
/// block of the current function, in the sense that it is either not derived
5352
/// from an llvm::Instruction (but from a global, constant, etc.) or that
5453
/// instruction is part of the entry basic block.
5554
///
56-
/// In other words, whatever value the result of getLVal()/getRVal() might be
57-
/// derived from then certainly dominates uses in all other basic blocks of
58-
/// the function.
55+
/// In other words, whatever the value might be derived from from then
56+
/// certainly dominates uses in all other basic blocks of the function.
5957
virtual bool definedInFuncEntryBB();
6058

59+
virtual DRValue *getRVal() { return nullptr; }
60+
6161
virtual DLValue *isLVal() { return nullptr; }
6262
virtual DSpecialRefValue *isSpecialRef() { return nullptr; }
63+
64+
virtual DRValue *isRVal() { return nullptr; }
6365
virtual DImValue *isIm() { return nullptr; }
6466
virtual DConstValue *isConst() { return nullptr; }
6567
virtual DNullValue *isNull() { return nullptr; }
@@ -69,22 +71,32 @@ class DValue {
6971
protected:
7072
llvm::Value *const val;
7173

72-
DValue(Type *t, llvm::Value *v) : type(t), val(v) {
73-
assert(type);
74-
assert(val);
75-
}
74+
DValue(Type *t, llvm::Value *v);
75+
76+
friend llvm::Value *DtoRVal(DValue *v);
77+
};
78+
79+
/// Represents a D rvalue via a low-level rvalue.
80+
class DRValue : public DValue {
81+
public:
82+
DRValue *getRVal() override { return this; }
83+
84+
DRValue *isRVal() override { return this; }
85+
86+
protected:
87+
DRValue(Type *t, llvm::Value *v);
7688
};
7789

78-
// immediate d-value
79-
class DImValue : public DValue {
90+
/// Represents an immediate D value via a low-level rvalue.
91+
class DImValue : public DRValue {
8092
public:
81-
DImValue(Type *t, llvm::Value *v);
93+
DImValue(Type *t, llvm::Value *v) : DRValue(t, v) {}
8294

8395
DImValue *isIm() override { return this; }
8496
};
8597

86-
// constant d-value
87-
class DConstValue : public DValue {
98+
/// Represents a constant D value via a low-level constant.
99+
class DConstValue : public DRValue {
88100
public:
89101
DConstValue(Type *t, llvm::Constant *con);
90102

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

96-
// null d-value
108+
/// Represents a D null constant.
97109
class DNullValue : public DConstValue {
98110
public:
99111
DNullValue(Type *t, llvm::Constant *con) : DConstValue(t, con) {}
100112

101113
DNullValue *isNull() override { return this; }
102114
};
103115

116+
/// Represents a D slice (dynamic array).
117+
class DSliceValue : public DRValue {
118+
public:
119+
DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr);
120+
121+
DSliceValue *isSlice() override { return this; }
122+
123+
llvm::Value *getLength();
124+
llvm::Value *getPtr();
125+
};
126+
127+
/// Represents a D function value with optional this/context pointer.
128+
class DFuncValue : public DRValue {
129+
public:
130+
FuncDeclaration *func;
131+
llvm::Value *vthis;
132+
133+
DFuncValue(Type *t, FuncDeclaration *fd, llvm::Value *v,
134+
llvm::Value *vt = nullptr);
135+
DFuncValue(FuncDeclaration *fd, llvm::Value *v, llvm::Value *vt = nullptr);
136+
137+
bool definedInFuncEntryBB() override;
138+
139+
DFuncValue *isFunc() override { return this; }
140+
};
141+
104142
/// Represents a D value in memory via a low-level lvalue.
105143
/// This doesn't imply that the D value is an lvalue too - e.g., we always
106144
/// keep structs and static arrays in memory.
107145
class DLValue : public DValue {
108146
public:
109147
DLValue(Type *t, llvm::Value *v);
110148

111-
virtual llvm::Value *getLVal() { return val; }
112-
llvm::Value *getRVal() override;
149+
DRValue *getRVal() override;
150+
virtual DLValue *getLVal() { return this; }
113151

114152
DLValue *isLVal() override { return this; }
115153

116154
protected:
117155
DLValue(llvm::Value *v, Type *t) : DValue(t, v) {}
156+
157+
friend llvm::Value *DtoLVal(DValue *v);
118158
};
119159

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

165+
DRValue *getRVal() override;
166+
DLValue *getLVal() override;
125167
llvm::Value *getRefStorage() { return val; }
126-
llvm::Value *getLVal() override;
127-
llvm::Value *getRVal() override;
128168

129169
DSpecialRefValue *isSpecialRef() override { return this; }
130170
};
131171

132-
// slice d-value
133-
class DSliceValue : public DValue {
134-
public:
135-
DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr);
136-
137-
DSliceValue *isSlice() override { return this; }
138172

139-
llvm::Value *getLength();
140-
llvm::Value *getPtr();
141-
};
142-
143-
// function d-value
144-
class DFuncValue : public DValue {
145-
public:
146-
FuncDeclaration *func;
147-
llvm::Value *vthis;
148-
149-
DFuncValue(Type *t, FuncDeclaration *fd, llvm::Value *v,
150-
llvm::Value *vt = nullptr);
151-
DFuncValue(FuncDeclaration *fd, llvm::Value *v, llvm::Value *vt = nullptr);
152-
153-
bool definedInFuncEntryBB() override;
154-
155-
DFuncValue *isFunc() override { return this; }
156-
};
173+
inline llvm::Value *DtoRVal(DValue *v) { return v->getRVal()->val; }
174+
llvm::Value *DtoLVal(DValue *v);
157175

158176
#endif // LDC_GEN_DVALUE_H

gen/llvmhelpers.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,13 +1869,3 @@ DValue *makeVarDValue(Type *type, VarDeclaration *vd, llvm::Value *storage) {
18691869

18701870
return new DLValue(type, val);
18711871
}
1872-
1873-
LLValue *DtoRVal(DValue *v) { return v->getRVal(); }
1874-
LLValue *DtoLVal(DValue *v) {
1875-
auto lval = v->isLVal();
1876-
assert(lval);
1877-
return lval->getLVal();
1878-
}
1879-
1880-
LLValue *DtoRVal(Expression *e) { return DtoRVal(toElem(e)); }
1881-
LLValue *DtoLVal(Expression *e) { return DtoLVal(toElem(e)); }

gen/llvmhelpers.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,8 @@ DValue *toElem(Expression *e, bool tryGetLvalue);
280280
DValue *toElemDtor(Expression *e);
281281
LLConstant *toConstElem(Expression *e, IRState *p);
282282

283-
llvm::Value *DtoRVal(DValue *v);
284-
llvm::Value *DtoRVal(Expression *e);
285-
llvm::Value *DtoLVal(DValue *v);
286-
llvm::Value *DtoLVal(Expression *e);
283+
inline llvm::Value *DtoRVal(Expression *e) { return DtoRVal(toElem(e)); }
284+
inline llvm::Value *DtoLVal(Expression *e) { return DtoLVal(toElem(e)); }
287285

288286
/// Creates a DLValue for the given VarDeclaration.
289287
///

gen/toir.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
165165
DtoAssign(loc, &field, val, TOKconstruct, true);
166166

167167
if (expr && expr->isLvalue()) {
168-
callPostblit(loc, expr, field.getLVal());
168+
callPostblit(loc, expr, DtoLVal(&field));
169169
}
170170

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

0 commit comments

Comments
 (0)