Skip to content

Commit 9f728a4

Browse files
authored
Merge pull request #1623 from kinke/evalorder
Fix evaluation order issues (continuation of #1620)
2 parents 278a5e9 + 2a0a663 commit 9f728a4

File tree

15 files changed

+481
-595
lines changed

15 files changed

+481
-595
lines changed

ddmd/expression.d

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,11 +2362,6 @@ public:
23622362
ubyte size; // # of bytes in Expression so we can copy() it
23632363
ubyte parens; // if this is a parenthesized expression
23642364

2365-
version(IN_LLVM)
2366-
{
2367-
void* cachedLvalue; // llvm::Value*
2368-
}
2369-
23702365
final extern (D) this(Loc loc, TOK op, int size)
23712366
{
23722367
//printf("Expression::Expression(op = %d) this = %p\n", op, this);

ddmd/expression.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,6 @@ class Expression : public RootObject
135135
unsigned char size; // # of bytes in Expression so we can copy() it
136136
unsigned char parens; // if this is a parenthesized expression
137137

138-
#if IN_LLVM
139-
llvm::Value* cachedLvalue;
140-
#endif
141-
142138
Expression(Loc loc, TOK op, int size);
143139
static void _init();
144140
Expression *copy();

gen/arrays.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,11 +590,11 @@ void initializeArrayLiteral(IRState *p, ArrayLiteralExp *ale, LLValue *dstMem) {
590590
} else {
591591
// Store the elements one by one.
592592
for (size_t i = 0; i < elemCount; ++i) {
593-
DValue *e = toElem(indexArrayLiteral(ale, i));
593+
DValue *rhs = toElem(indexArrayLiteral(ale, i));
594594

595-
LLValue *elemAddr = DtoGEPi(dstMem, 0, i, "", p->scopebb());
596-
auto vv = new DLValue(e->type, elemAddr);
597-
DtoAssign(ale->loc, vv, e, TOKconstruct, true);
595+
LLValue *lhsPtr = DtoGEPi(dstMem, 0, i, "", p->scopebb());
596+
DLValue lhs(rhs->type, DtoBitCast(lhsPtr, DtoPtrToType(rhs->type)));
597+
DtoAssign(ale->loc, &lhs, rhs, TOKconstruct, true);
598598
}
599599
}
600600
}

gen/binops.cpp

Lines changed: 237 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,102 +7,295 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
#include "gen/llvm.h"
10+
#include "gen/binops.h"
1111
#include "declaration.h"
1212
#include "gen/complex.h"
1313
#include "gen/dvalue.h"
1414
#include "gen/irstate.h"
15+
#include "gen/llvm.h"
1516
#include "gen/llvmhelpers.h"
1617
#include "gen/logger.h"
1718
#include "gen/tollvm.h"
1819

1920
//////////////////////////////////////////////////////////////////////////////
2021

21-
DImValue *DtoBinAdd(DRValue *lhs, DRValue *rhs) {
22-
Type *t = lhs->type;
23-
LLValue *l = DtoRVal(lhs);
24-
LLValue *r = DtoRVal(rhs);
22+
dinteger_t undoStrideMul(Loc &loc, Type *t, dinteger_t offset) {
23+
assert(t->ty == Tpointer);
24+
d_uns64 elemSize = t->nextOf()->size(loc);
25+
assert((offset % elemSize) == 0 &&
26+
"Expected offset by an integer amount of elements");
2527

26-
LLValue *res;
27-
if (t->isfloating()) {
28-
res = gIR->ir->CreateFAdd(l, r);
28+
return offset / elemSize;
29+
}
30+
31+
//////////////////////////////////////////////////////////////////////////////
32+
33+
namespace {
34+
struct RVals {
35+
DRValue *lhs, *rhs;
36+
};
37+
38+
RVals evalSides(DValue *lhs, Expression *rhs, bool loadLhsAfterRhs) {
39+
RVals rvals;
40+
41+
if (!loadLhsAfterRhs) {
42+
rvals.lhs = lhs->getRVal();
43+
rvals.rhs = toElem(rhs)->getRVal();
2944
} else {
30-
res = gIR->ir->CreateAdd(l, r);
45+
rvals.rhs = toElem(rhs)->getRVal();
46+
rvals.lhs = lhs->getRVal();
3147
}
3248

33-
return new DImValue(t, res);
49+
return rvals;
3450
}
3551

36-
//////////////////////////////////////////////////////////////////////////////
52+
/// Tries to remove a MulExp by a constant value of baseSize from e. Returns
53+
/// NULL if not possible.
54+
Expression *extractNoStrideInc(Expression *e, d_uns64 baseSize, bool &negate) {
55+
MulExp *mul;
56+
while (true) {
57+
if (e->op == TOKneg) {
58+
negate = !negate;
59+
e = static_cast<NegExp *>(e)->e1;
60+
continue;
61+
}
3762

38-
DImValue *DtoBinSub(DRValue *lhs, DRValue *rhs) {
39-
Type *t = lhs->type;
40-
LLValue *l = DtoRVal(lhs);
41-
LLValue *r = DtoRVal(rhs);
63+
if (e->op == TOKmul) {
64+
mul = static_cast<MulExp *>(e);
65+
break;
66+
}
4267

43-
LLValue *res;
44-
if (t->isfloating()) {
45-
res = gIR->ir->CreateFSub(l, r);
68+
return nullptr;
69+
}
70+
71+
if (!mul->e2->isConst()) {
72+
return nullptr;
73+
}
74+
dinteger_t stride = mul->e2->toInteger();
75+
76+
if (stride != baseSize) {
77+
return nullptr;
78+
}
79+
80+
return mul->e1;
81+
}
82+
83+
DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset,
84+
bool negateOffset, Type *resultType,
85+
bool loadLhsAfterRhs) {
86+
// The operand emitted by the frontend is in units of bytes, and not
87+
// pointer elements. We try to undo this before resorting to
88+
// temporarily bitcasting the pointer to i8.
89+
90+
LLValue *llBase = nullptr;
91+
LLValue *llOffset = nullptr;
92+
LLValue *llResult = nullptr;
93+
94+
if (offset->isConst()) {
95+
llBase = DtoRVal(base);
96+
dinteger_t byteOffset = offset->toInteger();
97+
if (byteOffset == 0) {
98+
llResult = llBase;
99+
} else {
100+
llOffset = DtoConstSize_t(undoStrideMul(loc, base->type, byteOffset));
101+
}
46102
} else {
47-
res = gIR->ir->CreateSub(l, r);
103+
Expression *noStrideInc = extractNoStrideInc(
104+
offset, base->type->nextOf()->size(loc), negateOffset);
105+
auto rvals =
106+
evalSides(base, noStrideInc ? noStrideInc : offset, loadLhsAfterRhs);
107+
llBase = DtoRVal(rvals.lhs);
108+
llOffset = DtoRVal(rvals.rhs);
109+
if (!noStrideInc) // byte offset => cast base to i8*
110+
llBase = DtoBitCast(llBase, getVoidPtrType());
111+
}
112+
113+
if (!llResult) {
114+
if (negateOffset)
115+
llOffset = gIR->ir->CreateNeg(llOffset);
116+
llResult = DtoGEP1(llBase, llOffset, false);
48117
}
49118

50-
return new DImValue(t, res);
119+
return new DImValue(resultType, DtoBitCast(llResult, DtoType(resultType)));
120+
}
51121
}
52122

53123
//////////////////////////////////////////////////////////////////////////////
54124

55-
DImValue *DtoBinMul(Type *targettype, DRValue *lhs, DRValue *rhs) {
56-
Type *t = lhs->type;
57-
LLValue *l = DtoRVal(lhs);
58-
LLValue *r = DtoRVal(rhs);
125+
DValue *binAdd(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
126+
bool loadLhsAfterRhs) {
127+
Type *lhsType = lhs->type->toBasetype();
128+
Type *rhsType = rhs->type->toBasetype();
59129

60-
LLValue *res;
61-
if (t->isfloating()) {
62-
res = gIR->ir->CreateFMul(l, r);
63-
} else {
64-
res = gIR->ir->CreateMul(l, r);
130+
if (lhsType != rhsType && lhsType->ty == Tpointer && rhsType->isintegral()) {
131+
Logger::println("Adding integer to pointer");
132+
return emitPointerOffset(loc, lhs, rhs, false, type, loadLhsAfterRhs);
65133
}
66134

67-
return new DImValue(targettype, res);
135+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
136+
137+
if (type->iscomplex())
138+
return DtoComplexAdd(loc, type, rvals.lhs, rvals.rhs);
139+
140+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
141+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
142+
LLValue *res = (type->isfloating() ? gIR->ir->CreateFAdd(l, r)
143+
: gIR->ir->CreateAdd(l, r));
144+
145+
return new DImValue(type, res);
68146
}
69147

70148
//////////////////////////////////////////////////////////////////////////////
71149

72-
DImValue *DtoBinDiv(Type *targettype, DRValue *lhs, DRValue *rhs) {
73-
Type *t = lhs->type;
74-
LLValue *l = DtoRVal(lhs);
75-
LLValue *r = DtoRVal(rhs);
150+
DValue *binMin(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
151+
bool loadLhsAfterRhs) {
152+
Type *lhsType = lhs->type->toBasetype();
153+
Type *rhsType = rhs->type->toBasetype();
76154

155+
if (lhsType != rhsType && lhsType->ty == Tpointer && rhsType->isintegral()) {
156+
Logger::println("Subtracting integer from pointer");
157+
return emitPointerOffset(loc, lhs, rhs, true, type, loadLhsAfterRhs);
158+
}
159+
160+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
161+
162+
if (lhsType->ty == Tpointer && rhsType->ty == Tpointer) {
163+
LLValue *l = DtoRVal(rvals.lhs);
164+
LLValue *r = DtoRVal(rvals.rhs);
165+
LLType *llSizeT = DtoSize_t();
166+
l = gIR->ir->CreatePtrToInt(l, llSizeT);
167+
r = gIR->ir->CreatePtrToInt(r, llSizeT);
168+
LLValue *diff = gIR->ir->CreateSub(l, r);
169+
LLType *llType = DtoType(type);
170+
if (diff->getType() != llType)
171+
diff = gIR->ir->CreateIntToPtr(diff, llType);
172+
return new DImValue(type, diff);
173+
}
174+
175+
if (type->iscomplex())
176+
return DtoComplexMin(loc, type, rvals.lhs, rvals.rhs);
177+
178+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
179+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
180+
LLValue *res = (type->isfloating() ? gIR->ir->CreateFSub(l, r)
181+
: gIR->ir->CreateSub(l, r));
182+
183+
return new DImValue(type, res);
184+
}
185+
186+
//////////////////////////////////////////////////////////////////////////////
187+
188+
DValue *binMul(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
189+
bool loadLhsAfterRhs) {
190+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
191+
192+
if (type->iscomplex())
193+
return DtoComplexMul(loc, type, rvals.lhs, rvals.rhs);
194+
195+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
196+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
197+
LLValue *res = (type->isfloating() ? gIR->ir->CreateFMul(l, r)
198+
: gIR->ir->CreateMul(l, r));
199+
200+
return new DImValue(type, res);
201+
}
202+
203+
//////////////////////////////////////////////////////////////////////////////
204+
205+
DValue *binDiv(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
206+
bool loadLhsAfterRhs) {
207+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
208+
209+
if (type->iscomplex())
210+
return DtoComplexDiv(loc, type, rvals.lhs, rvals.rhs);
211+
212+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
213+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
77214
LLValue *res;
78-
if (t->isfloating()) {
215+
if (type->isfloating()) {
79216
res = gIR->ir->CreateFDiv(l, r);
80-
} else if (!isLLVMUnsigned(t)) {
217+
} else if (!isLLVMUnsigned(type)) {
81218
res = gIR->ir->CreateSDiv(l, r);
82219
} else {
83220
res = gIR->ir->CreateUDiv(l, r);
84221
}
85222

86-
return new DImValue(targettype, res);
223+
return new DImValue(type, res);
87224
}
88225

89226
//////////////////////////////////////////////////////////////////////////////
90227

91-
DImValue *DtoBinRem(Type *targettype, DRValue *lhs, DRValue *rhs) {
92-
Type *t = lhs->type;
93-
LLValue *l = DtoRVal(lhs);
94-
LLValue *r = DtoRVal(rhs);
228+
DValue *binMod(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
229+
bool loadLhsAfterRhs) {
230+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
95231

232+
if (type->iscomplex())
233+
return DtoComplexMod(loc, type, rvals.lhs, rvals.rhs);
234+
235+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
236+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
96237
LLValue *res;
97-
if (t->isfloating()) {
238+
if (type->isfloating()) {
98239
res = gIR->ir->CreateFRem(l, r);
99-
} else if (!isLLVMUnsigned(t)) {
240+
} else if (!isLLVMUnsigned(type)) {
100241
res = gIR->ir->CreateSRem(l, r);
101242
} else {
102243
res = gIR->ir->CreateURem(l, r);
103244
}
104245

105-
return new DImValue(targettype, res);
246+
return new DImValue(type, res);
247+
}
248+
249+
//////////////////////////////////////////////////////////////////////////////
250+
251+
namespace {
252+
DValue *binBitwise(llvm::Instruction::BinaryOps binOp, Loc &loc, Type *type,
253+
DValue *lhs, Expression *rhs, bool loadLhsAfterRhs) {
254+
auto rvals = evalSides(lhs, rhs, loadLhsAfterRhs);
255+
256+
LLValue *l = DtoRVal(DtoCast(loc, rvals.lhs, type));
257+
LLValue *r = DtoRVal(DtoCast(loc, rvals.rhs, type));
258+
LLValue *res = llvm::BinaryOperator::Create(binOp, l, r, "", gIR->scopebb());
259+
260+
return new DImValue(type, res);
261+
}
262+
}
263+
264+
DValue *binAnd(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
265+
bool loadLhsAfterRhs) {
266+
return binBitwise(llvm::Instruction::And, loc, type, lhs, rhs,
267+
loadLhsAfterRhs);
268+
}
269+
270+
DValue *binOr(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
271+
bool loadLhsAfterRhs) {
272+
return binBitwise(llvm::Instruction::Or, loc, type, lhs, rhs,
273+
loadLhsAfterRhs);
274+
}
275+
276+
DValue *binXor(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
277+
bool loadLhsAfterRhs) {
278+
return binBitwise(llvm::Instruction::Xor, loc, type, lhs, rhs,
279+
loadLhsAfterRhs);
280+
}
281+
282+
DValue *binShl(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
283+
bool loadLhsAfterRhs) {
284+
return binBitwise(llvm::Instruction::Shl, loc, type, lhs, rhs,
285+
loadLhsAfterRhs);
286+
}
287+
288+
DValue *binShr(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
289+
bool loadLhsAfterRhs) {
290+
auto op = (isLLVMUnsigned(type) ? llvm::Instruction::LShr
291+
: llvm::Instruction::AShr);
292+
return binBitwise(op, loc, type, lhs, rhs, loadLhsAfterRhs);
293+
}
294+
295+
DValue *binUshr(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
296+
bool loadLhsAfterRhs) {
297+
return binBitwise(llvm::Instruction::LShr, loc, type, lhs, rhs,
298+
loadLhsAfterRhs);
106299
}
107300

108301
//////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)