Skip to content

Commit ca50d94

Browse files
committed
Revise DValue repainting
Fixes #3990.
1 parent 8863a80 commit ca50d94

File tree

3 files changed

+59
-48
lines changed

3 files changed

+59
-48
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Supports LLVM 9.0 - 14.0.
1414

1515
#### Bug fixes
16+
- Report unexpected type repaints as fatal ICEs instead of crashing. (#3990, #3991)
1617

1718
#### Internals
1819
- Main CI was moved from Azure Pipelines to GitHub Actions. Any fork on GitHub can trivially reuse the fully automated prebuilt packages generation & upload to a GitHub release. (#3978)

gen/llvmhelpers.cpp

+35-48
Original file line numberDiff line numberDiff line change
@@ -771,58 +771,45 @@ DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to) {
771771
IF_LOG Logger::println("repainting from '%s' to '%s'", from->toChars(),
772772
to->toChars());
773773

774-
if (from->ty == TY::Tarray) {
775-
Type *at = to->toBasetype();
776-
assert(at->ty == TY::Tarray);
777-
Type *elem = at->nextOf()->pointerTo();
778-
if (DSliceValue *slice = val->isSlice()) {
779-
return new DSliceValue(to, slice->getLength(),
780-
DtoBitCast(slice->getPtr(), DtoType(elem)));
774+
Type *tb = to->toBasetype();
775+
776+
if (val->isLVal()) {
777+
auto ptr = DtoBitCast(DtoLVal(val), DtoPtrToType(tb));
778+
return new DLValue(to, ptr);
779+
}
780+
781+
if (auto slice = val->isSlice()) {
782+
if (tb->ty == TY::Tarray) {
783+
auto ptr = DtoBitCast(slice->getPtr(), DtoPtrToType(tb->nextOf()));
784+
return new DSliceValue(to, slice->getLength(), ptr);
781785
}
782-
if (val->isLVal()) {
783-
LLValue *ptr = DtoLVal(val);
784-
ptr = DtoBitCast(ptr, DtoType(at->pointerTo()));
785-
return new DLValue(to, ptr);
786+
} else if (auto func = val->isFunc()) {
787+
if (tb->ty == TY::Tdelegate) {
788+
auto funcptr =
789+
DtoBitCast(DtoRVal(func), DtoType(tb)->getContainedType(1));
790+
return new DFuncValue(to, func->func, funcptr, func->vthis);
786791
}
787-
LLValue *len, *ptr;
788-
len = DtoArrayLen(val);
789-
ptr = DtoArrayPtr(val);
790-
ptr = DtoBitCast(ptr, DtoType(elem));
791-
return new DImValue(to, DtoAggrPair(len, ptr));
792-
}
793-
if (from->ty == TY::Tdelegate) {
794-
Type *dgty = to->toBasetype();
795-
assert(dgty->ty == TY::Tdelegate);
796-
if (val->isLVal()) {
797-
LLValue *ptr = DtoLVal(val);
798-
assert(isaPointer(ptr));
799-
ptr = DtoBitCast(ptr, DtoPtrToType(dgty));
800-
IF_LOG Logger::cout() << "dg ptr: " << *ptr << '\n';
801-
return new DLValue(to, ptr);
792+
} else { // generic rvalue
793+
LLValue *rval = DtoRVal(val);
794+
LLType *tll = DtoType(tb);
795+
796+
if (rval->getType() == tll) {
797+
return new DImValue(to, rval);
798+
}
799+
if (rval->getType()->isPointerTy() && tll->isPointerTy()) {
800+
return new DImValue(to, DtoBitCast(rval, tll));
801+
}
802+
if (from->ty == TY::Tdelegate && tb->ty == TY::Tdelegate) {
803+
LLValue *context = gIR->ir->CreateExtractValue(rval, 0, ".context");
804+
LLValue *funcptr = gIR->ir->CreateExtractValue(rval, 1, ".funcptr");
805+
funcptr = DtoBitCast(funcptr, tll->getContainedType(1));
806+
return new DImValue(to, DtoAggrPair(context, funcptr));
802807
}
803-
LLValue *dg = DtoRVal(val);
804-
LLValue *context = gIR->ir->CreateExtractValue(dg, 0, ".context");
805-
LLValue *funcptr = gIR->ir->CreateExtractValue(dg, 1, ".funcptr");
806-
funcptr = DtoBitCast(funcptr, DtoType(dgty)->getContainedType(1));
807-
LLValue *aggr = DtoAggrPair(context, funcptr);
808-
IF_LOG Logger::cout() << "dg: " << *aggr << '\n';
809-
return new DImValue(to, aggr);
810-
}
811-
if (from->ty == TY::Tpointer || from->ty == TY::Tclass ||
812-
from->ty == TY::Taarray) {
813-
Type *b = to->toBasetype();
814-
assert(b->ty == TY::Tpointer || b->ty == TY::Tclass ||
815-
b->ty == TY::Taarray);
816-
LLValue *ptr = DtoBitCast(DtoRVal(val), DtoType(b));
817-
return new DImValue(to, ptr);
818-
}
819-
if (from->ty == TY::Tsarray) {
820-
assert(to->toBasetype()->ty == TY::Tsarray);
821-
LLValue *ptr = DtoBitCast(DtoLVal(val), DtoPtrToType(to));
822-
return new DLValue(to, ptr);
823808
}
824-
assert(DtoType(from) == DtoType(to));
825-
return new DImValue(to, DtoRVal(val));
809+
810+
error(loc, "ICE: unexpected type repaint from `%s` to `%s`", from->toChars(),
811+
to->toChars());
812+
fatal();
826813
}
827814

828815
/******************************************************************************

tests/compilable/gh3990.d

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %ldc -c %s
2+
3+
struct Vector
4+
{
5+
float x, y, z;
6+
}
7+
8+
struct QAngle
9+
{
10+
float x, y, z;
11+
12+
QAngle opOpAssign(string op)(const(QAngle))
13+
{
14+
return this;
15+
}
16+
}
17+
18+
void OnUserCmdPre()
19+
{
20+
Vector ss;
21+
QAngle dd;
22+
dd -= cast(QAngle)ss;
23+
}

0 commit comments

Comments
 (0)