mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 08:01:11 +03:00
Fix array casts with constant source lengths
The `__ArrayCast` lowering isn't (always?) done when casting a static array to a slice with different element size. So exploit constant source lengths and compute the target length at compile-time. This fixes compilable/ldc_github_421.d - a float[16] can be cast to a float4[] with constant length 4.
This commit is contained in:
parent
0e2173bf82
commit
9469c6b5b8
1 changed files with 16 additions and 17 deletions
|
@ -1263,38 +1263,37 @@ DValue *DtoCastArray(Loc &loc, DValue *u, Type *to) {
|
|||
LLValue *length = nullptr;
|
||||
LLValue *ptr = nullptr;
|
||||
if (fromtype->ty == Tsarray) {
|
||||
uinteger_t len = static_cast<TypeSArray *>(fromtype)->dim->toUInteger();
|
||||
length = DtoConstSize_t(len);
|
||||
length = DtoConstSize_t(
|
||||
static_cast<TypeSArray *>(fromtype)->dim->toUInteger());
|
||||
ptr = DtoLVal(u);
|
||||
assert(isaPointer(ptr->getType()));
|
||||
LLArrayType *arrty = isaArray(ptr->getType()->getContainedType(0));
|
||||
|
||||
if (arrty->getNumElements() * fromtype->nextOf()->size() %
|
||||
totype->nextOf()->size() !=
|
||||
0) {
|
||||
error(loc,
|
||||
"invalid cast from `%s` to `%s`, the element sizes don't line up",
|
||||
fromtype->toChars(), totype->toChars());
|
||||
fatal();
|
||||
}
|
||||
} else {
|
||||
length = DtoArrayLen(u);
|
||||
ptr = DtoArrayPtr(u);
|
||||
}
|
||||
|
||||
LLType *ptrty = DtoArrayType(totype)->getContainedType(1);
|
||||
|
||||
const auto fsize = fromtype->nextOf()->size();
|
||||
const auto tsize = totype->nextOf()->size();
|
||||
if (fsize != tsize) {
|
||||
if (fsize % tsize == 0) {
|
||||
// set new length to `length * (fsize / tsize)`
|
||||
if (auto constLength = isaConstantInt(length)) {
|
||||
// compute new constant length: (constLength * fsize) / tsize
|
||||
const auto totalSize = constLength->getZExtValue() * fsize;
|
||||
if (totalSize % tsize != 0) {
|
||||
error(loc,
|
||||
"invalid cast from `%s` to `%s`, the element sizes don't "
|
||||
"line up",
|
||||
fromtype->toChars(), totype->toChars());
|
||||
fatal();
|
||||
}
|
||||
length = DtoConstSize_t(totalSize / tsize);
|
||||
} else if (fsize % tsize == 0) {
|
||||
// compute new dynamic length: length * (fsize / tsize)
|
||||
length = gIR->ir->CreateMul(length, DtoConstSize_t(fsize / tsize));
|
||||
} else {
|
||||
llvm_unreachable("should have been lowered to `__ArrayCast`");
|
||||
}
|
||||
}
|
||||
|
||||
LLType *ptrty = tolltype->getStructElementType(1);
|
||||
return new DSliceValue(to, length, DtoBitCast(ptr, ptrty));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue