Skip to content

Commit 4a5253d

Browse files
authored
Fix assertion when compiling array of struct init (microsoft#6814)
In CGHLSLMSFinishCodeGen's BuildImmInit, when initializing an array, if the init value type doesn't match the array element type, we must bail and instead, have it inject a call to the global ctor. Without this, builds with asserts enabled would assert later with "Wrong type in array element initializer". In non-assert builds, this invalid IR would be removed, and valid code emitted. See microsoft#5294
1 parent 4a3a5da commit 4a5253d

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

tools/clang/lib/CodeGen/CGHLSLMSFinishCodeGen.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2966,7 +2966,6 @@ bool BuildImmInit(Function *Ctor) {
29662966
allConst = false;
29672967
break;
29682968
}
2969-
ImmList.emplace_back(cast<Constant>(V));
29702969
Value *Ptr = SI->getPointerOperand();
29712970
if (GEPOperator *GepOp = dyn_cast<GEPOperator>(Ptr)) {
29722971
Ptr = GepOp->getPointerOperand();
@@ -2978,6 +2977,15 @@ bool BuildImmInit(Function *Ctor) {
29782977
}
29792978
}
29802979
}
2980+
// If initializing an array, make sure init value type matches array
2981+
// element type
2982+
llvm::Type *GVElemTy = GV->getType()->getElementType();
2983+
if (llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(GVElemTy)) {
2984+
llvm::Type *ElTy = AT->getElementType();
2985+
if (V->getType() != ElTy)
2986+
return false;
2987+
}
2988+
ImmList.emplace_back(cast<Constant>(V));
29812989
} else {
29822990
if (!isa<ReturnInst>(*I)) {
29832991
allConst = false;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %dxc -T cs_6_0 %s -fcgl | FileCheck %s
2+
3+
// Compiling this HLSL used to trigger this assert:
4+
//
5+
// Error: assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer")
6+
// File:
7+
// ..\..\third_party\dawn\third_party\dxc\lib\IR\Constants.cpp(886)
8+
// Func: static llvm::ConstantArray::getImpl
9+
//
10+
// Reported in https://github.com/microsoft/DirectXShaderCompiler/issues/5294
11+
//
12+
// Bug was fixed in CGHLSLMSFinishCodeGen in BuildImmInit: when initializing an array,
13+
// if the init value type doesn't match the array element type, bail. We check that
14+
// a call to the global ctor function is called.
15+
16+
// CHECK: define internal void @"\01??__EP@@YAXXZ"() #1 {
17+
// CHECK: store i32 0, i32* getelementptr inbounds ([4 x %struct.str], [4 x %struct.str]* @P, i32 0, i32 0, i32 0)
18+
// CHECK-NEXT: store i32 0, i32* getelementptr inbounds ([4 x %struct.str], [4 x %struct.str]* @P, i32 0, i32 1, i32 0)
19+
// CHECK-NEXT: store i32 0, i32* getelementptr inbounds ([4 x %struct.str], [4 x %struct.str]* @P, i32 0, i32 2, i32 0)
20+
// CHECK-NEXT: store i32 0, i32* getelementptr inbounds ([4 x %struct.str], [4 x %struct.str]* @P, i32 0, i32 3, i32 0)
21+
// CHECK-NEXT: ret void
22+
// CHECK-NEXT: }
23+
//
24+
// CHECK: define internal void @_GLOBAL__sub_I_construct_global_array_of_struct.hlsl() #1 {
25+
// CHECK: call void @"\01??__EP@@YAXXZ"()
26+
// CHECK-NEXT: ret void
27+
// CHECK-NEXT: }
28+
29+
struct str {
30+
int i;
31+
};
32+
33+
str func(inout str pointer) {
34+
return pointer;
35+
}
36+
37+
static str P[4] = (str[4])0;
38+
39+
[numthreads(1, 1, 1)]
40+
void main() {
41+
const str r = func(P[2]);
42+
return;
43+
}

0 commit comments

Comments
 (0)