Skip to content

Commit 3048d5d

Browse files
csyongheTim Foley
authored and
Tim Foley
committed
Fixup handling of empty structs in function return types and parameters. (shader-slang#796)
* Fixup handling of empty structs in function return types and parameters. * Bug fix in legalizeFunc() * More comprehensive empty struct test * Fix `legalizeFieldExtract` for empty struct field. * Add empty struct handling for construct inst
1 parent 8171a55 commit 3048d5d

File tree

3 files changed

+125
-32
lines changed

3 files changed

+125
-32
lines changed

source/slang/ir-legalize-types.cpp

+69-32
Original file line numberDiff line numberDiff line change
@@ -129,25 +129,6 @@ static LegalType legalizeType(
129129
return legalizeType(context->typeLegalizationContext, type);
130130
}
131131

132-
// Legalize a type, and then expect it to
133-
// result in a simple type.
134-
static IRType* legalizeSimpleType(
135-
IRTypeLegalizationContext* context,
136-
IRType* type)
137-
{
138-
auto legalType = legalizeType(context, type);
139-
switch (legalType.flavor)
140-
{
141-
case LegalType::Flavor::simple:
142-
return legalType.getSimple();
143-
144-
default:
145-
// TODO: need to issue a diagnostic here.
146-
SLANG_UNEXPECTED("unexpected type case");
147-
break;
148-
}
149-
}
150-
151132
// Take a value that is being used as an operand,
152133
// and turn it into the equivalent legalized value.
153134
static LegalVal legalizeOperand(
@@ -209,21 +190,47 @@ static LegalVal legalizeCall(
209190
IRTypeLegalizationContext* context,
210191
IRCall* callInst)
211192
{
212-
// TODO: implement legalization of non-simple return types
213193
auto retType = legalizeType(context, callInst->getFullType());
214-
SLANG_ASSERT(retType.flavor == LegalType::Flavor::simple);
194+
IRType* retIRType = nullptr;
195+
switch (retType.flavor)
196+
{
197+
case LegalType::Flavor::simple:
198+
retIRType = retType.getSimple();
199+
break;
200+
case LegalType::Flavor::none:
201+
retIRType = context->builder->getVoidType();
202+
break;
203+
default:
204+
// TODO: implement legalization of non-simple return types
205+
SLANG_UNEXPECTED("unimplemented legalized return type for IRInstCall.");
206+
}
215207

216208
List<IRInst*> instArgs;
217209
for (auto i = 1u; i < callInst->getOperandCount(); i++)
218210
getArgumentValues(instArgs, legalizeOperand(context, callInst->getOperand(i)));
219211

220212
return LegalVal::simple(context->builder->emitCallInst(
221-
callInst->getFullType(),
213+
retIRType,
222214
callInst->getCallee(),
223215
instArgs.Count(),
224216
instArgs.Buffer()));
225217
}
226218

219+
static LegalVal legalizeRetVal(IRTypeLegalizationContext* context,
220+
LegalVal retVal)
221+
{
222+
switch (retVal.flavor)
223+
{
224+
case LegalVal::Flavor::simple:
225+
return LegalVal::simple(context->builder->emitReturn(retVal.getSimple()));
226+
case LegalVal::Flavor::none:
227+
return LegalVal::simple(context->builder->emitReturn());
228+
default:
229+
// TODO: implement legalization of non-simple return types
230+
SLANG_UNEXPECTED("unimplemented legalized return type for IRReturnVal.");
231+
}
232+
}
233+
227234
static LegalVal legalizeLoad(
228235
IRTypeLegalizationContext* context,
229236
LegalVal legalPtrVal)
@@ -343,6 +350,9 @@ static LegalVal legalizeFieldExtract(
343350
{
344351
auto builder = context->builder;
345352

353+
if (type.flavor == LegalType::Flavor::none)
354+
return LegalVal();
355+
346356
switch (legalStructOperand.flavor)
347357
{
348358
case LegalVal::Flavor::none:
@@ -459,6 +469,8 @@ static LegalVal legalizeFieldAddress(
459469
IRStructKey* fieldKey)
460470
{
461471
auto builder = context->builder;
472+
if (type.flavor == LegalType::Flavor::none)
473+
return LegalVal();
462474

463475
switch (legalPtrOperand.flavor)
464476
{
@@ -940,7 +952,20 @@ static LegalVal legalizeMakeStruct(
940952
}
941953
}
942954

943-
955+
static LegalVal legalizeConstruct(IRTypeLegalizationContext* context,
956+
LegalType type)
957+
{
958+
switch (type.flavor)
959+
{
960+
case LegalType::Flavor::none:
961+
return LegalVal();
962+
case LegalType::Flavor::simple:
963+
return LegalVal::simple(context->builder->emitConstructorInst(type.getSimple(), 0, nullptr));
964+
default:
965+
SLANG_UNEXPECTED("unhandled legalization case for construct inst.");
966+
UNREACHABLE_RETURN(LegalVal());
967+
}
968+
}
944969

945970
static LegalVal legalizeInst(
946971
IRTypeLegalizationContext* context,
@@ -970,14 +995,16 @@ static LegalVal legalizeInst(
970995

971996
case kIROp_Call:
972997
return legalizeCall(context, (IRCall*)inst);
973-
998+
case kIROp_ReturnVal:
999+
return legalizeRetVal(context, args[0]);
9741000
case kIROp_makeStruct:
9751001
return legalizeMakeStruct(
9761002
context,
9771003
type,
9781004
args,
9791005
inst->getOperandCount());
980-
1006+
case kIROp_Construct:
1007+
return legalizeConstruct(context, type);
9811008
case kIROp_undefined:
9821009
return LegalVal();
9831010
default:
@@ -1186,10 +1213,10 @@ static LegalVal legalizeInst(
11861213
// will, in general, depend on what we are doing.
11871214

11881215
// We will set up the IR builder so that any new
1189-
// instructions generated will be placed after
1216+
// instructions generated will be placed before
11901217
// the location of the original instruction.
11911218
auto builder = context->builder;
1192-
builder->setInsertBefore(inst->getNextInst());
1219+
builder->setInsertBefore(inst);
11931220

11941221
LegalVal legalVal = legalizeInst(
11951222
context,
@@ -1279,7 +1306,19 @@ static LegalVal legalizeFunc(
12791306
// TODO: we should give an error message when the result type of a function
12801307
// can't be legalized (e.g., trying to return a texture, or a structue that
12811308
// contains one).
1282-
IRType* newResultType = legalizeSimpleType(context, oldFuncType->getResultType());
1309+
auto legalReturnType = legalizeType(context, oldFuncType->getResultType());
1310+
IRType* newResultType = nullptr;
1311+
switch (legalReturnType.flavor)
1312+
{
1313+
case LegalType::Flavor::simple:
1314+
newResultType = legalReturnType.getSimple();
1315+
break;
1316+
case LegalType::Flavor::none:
1317+
newResultType = context->builder->getVoidType();
1318+
break;
1319+
default:
1320+
SLANG_UNEXPECTED("unknown legalized function return type.");
1321+
}
12831322
List<IRType*> newParamTypes;
12841323
for (UInt pp = 0; pp < oldParamCount; ++pp)
12851324
{
@@ -1295,7 +1334,6 @@ static LegalVal legalizeFunc(
12951334
context->builder->setDataType(irFunc, newFuncType);
12961335

12971336
legalizeInstsInParent(context, irFunc);
1298-
12991337
return LegalVal::simple(irFunc);
13001338
}
13011339

@@ -1360,10 +1398,9 @@ static LegalVal declareSimpleVar(
13601398

13611399
case kIROp_Var:
13621400
{
1401+
builder->setInsertBefore(context->insertBeforeLocalVar);
13631402
auto localVar = builder->emitVar(type);
1364-
localVar->removeFromParent();
1365-
localVar->insertBefore(context->insertBeforeLocalVar);
1366-
1403+
13671404
irVar = localVar;
13681405
legalVarVal = LegalVal::simple(irVar);
13691406

tests/compute/empty-struct2.slang

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//TEST(smoke,compute):COMPARE_COMPUTE:
2+
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
3+
// This is a basic test for Slang compute shader.
4+
5+
RWStructuredBuffer<uint> outputBuffer;
6+
7+
interface IInterface
8+
{
9+
associatedtype T;
10+
T getT();
11+
[mutating]
12+
void setT(T val);
13+
}
14+
interface IEmptyS
15+
{
16+
float emptyFunc();
17+
};
18+
struct EmptyS : IEmptyS
19+
{
20+
float emptyFunc() {return 0.0;}
21+
};
22+
23+
struct Empty<TT : IEmptyS> : IInterface
24+
{
25+
typedef TT T;
26+
TT value;
27+
float a;
28+
TT getT()
29+
{
30+
return value;
31+
}
32+
[mutating]
33+
void setT(TT val)
34+
{
35+
value = val;
36+
a = value.emptyFunc();
37+
}
38+
}
39+
40+
void test<Obj : IInterface>(Obj obj)
41+
{
42+
Obj.T v = obj.getT();
43+
obj.setT(v);
44+
}
45+
46+
[numthreads(4, 1, 1)]
47+
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
48+
{
49+
Empty<EmptyS> obj;
50+
test(obj);
51+
outputBuffer[dispatchThreadID.x] = dispatchThreadID.x;
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0
2+
1
3+
2
4+
3

0 commit comments

Comments
 (0)