Skip to content

Commit 4841731

Browse files
Merge pull request #31918 from aschwaighofer/irgen_enum_witness_huge_types
IRGen: Fix enumPayload value witness emission for huge types
2 parents a85ac89 + 940a6d7 commit 4841731

File tree

3 files changed

+80
-14
lines changed

3 files changed

+80
-14
lines changed

lib/IRGen/GenType.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -687,15 +687,26 @@ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload(
687687

688688
llvm::Value *caseIndexFromValue = zero;
689689
if (fixedSize > Size(0)) {
690-
// Read up to one pointer-sized 'chunk' of the payload.
691-
// The size of the chunk does not have to be a power of 2.
692-
auto *caseIndexType = llvm::IntegerType::get(Ctx,
693-
fixedSize.getValueInBits());
694-
auto *caseIndexAddr = Builder.CreateBitCast(valueAddr,
695-
caseIndexType->getPointerTo());
696-
caseIndexFromValue = Builder.CreateZExtOrTrunc(
697-
Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))),
698-
IGM.Int32Ty);
690+
// llvm only supports integer types upto a certain size (i.e selection dag
691+
// will crash).
692+
if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) {
693+
// Read up to one pointer-sized 'chunk' of the payload.
694+
// The size of the chunk does not have to be a power of 2.
695+
auto *caseIndexType =
696+
llvm::IntegerType::get(Ctx, fixedSize.getValueInBits());
697+
auto *caseIndexAddr =
698+
Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo());
699+
caseIndexFromValue = Builder.CreateZExtOrTrunc(
700+
Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))),
701+
IGM.Int32Ty);
702+
} else {
703+
auto *caseIndexType = llvm::IntegerType::get(Ctx, 32);
704+
auto *caseIndexAddr =
705+
Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo());
706+
caseIndexFromValue = Builder.CreateZExtOrTrunc(
707+
Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))),
708+
IGM.Int32Ty);
709+
}
699710
}
700711

701712
auto *result1 = Builder.CreateAdd(
@@ -867,11 +878,25 @@ void irgen::storeFixedTypeEnumTagSinglePayload(
867878
payloadIndex->addIncoming(payloadIndex0, payloadLT4BB);
868879

869880
if (fixedSize > Size(0)) {
870-
// Write the value to the payload as a zero extended integer.
871-
auto *intType = Builder.getIntNTy(fixedSize.getValueInBits());
872-
Builder.CreateStore(
873-
Builder.CreateZExtOrTrunc(payloadIndex, intType),
874-
Builder.CreateBitCast(valueAddr, intType->getPointerTo()));
881+
if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) {
882+
// Write the value to the payload as a zero extended integer.
883+
auto *intType = Builder.getIntNTy(fixedSize.getValueInBits());
884+
Builder.CreateStore(
885+
Builder.CreateZExtOrTrunc(payloadIndex, intType),
886+
Builder.CreateBitCast(valueAddr, intType->getPointerTo()));
887+
} else {
888+
// Write the value to the payload as a zero extended integer.
889+
Size limit = IGM.getPointerSize();
890+
auto *intType = Builder.getIntNTy(limit.getValueInBits());
891+
Builder.CreateStore(
892+
Builder.CreateZExtOrTrunc(payloadIndex, intType),
893+
Builder.CreateBitCast(valueAddr, intType->getPointerTo()));
894+
// Zero the remainder of the payload.
895+
auto zeroAddr = Builder.CreateConstByteArrayGEP(valueAddr, limit);
896+
auto zeroSize = Builder.CreateSub(
897+
size, llvm::ConstantInt::get(size->getType(), limit.getValue()));
898+
Builder.CreateMemSet(zeroAddr, Builder.getInt8(0), zeroSize);
899+
}
875900
}
876901
// Write to the extra tag bytes, if any.
877902
emitSetTag(IGF, extraTagBitsAddr, extraTagIndex, numExtraTagBytes);

test/IRGen/Inputs/huge_c_type.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <stdint.h>
2+
3+
typedef uint8_t bool;
4+
5+
#define CREATE_ARRAY(T, N) \
6+
struct { \
7+
T data[N]; \
8+
uint64_t size; \
9+
}
10+
11+
typedef struct {
12+
int32_t a;
13+
double b[16];
14+
} Thing;
15+
16+
typedef struct {
17+
uint64_t a;
18+
bool b;
19+
CREATE_ARRAY(Thing, 16) c;
20+
uint32_t d;
21+
uint64_t e;
22+
uint64_t f;
23+
CREATE_ARRAY(uint32_t, 4) g;
24+
CREATE_ARRAY(uint64_t, 4) h;
25+
CREATE_ARRAY(uint64_t, 4) i;
26+
} Thing2;
27+
28+
typedef struct {
29+
int64_t a;
30+
CREATE_ARRAY(Thing2, 512) c;
31+
} Thing3;

test/IRGen/huge_c_type.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -disable-llvm-optzns -emit-ir | %FileCheck %s
2+
// Make sure that this does not crash during LLVM's ISel. It does not like huge
3+
// llvm::IntegerTypes.
4+
// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -c
5+
6+
// CHECK-NOT:i9535616
7+
8+
public func doIt(a: Thing3) {
9+
print(a)
10+
}

0 commit comments

Comments
 (0)