summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-08-17 14:17:29 -0700
committerTim Foley <tfoley@nvidia.com>2017-08-17 14:17:29 -0700
commit95348fdb623509eb22c04d4c7c19af8228c5a533 (patch)
tree213fec5c06df3401fddd99d90c95f2ed7ccd2c9e /source
parentad19484792dcc5a1fb90720614830c66c4b9712d (diff)
[ir] Represent fields more direclty
Previously, a `StructType` was an ordinary instruction that took a variable number of types are operands, representing the types of fields. This ends up being inconvenient for a few reasons: - To add decorations to the fields, you'd end up having to decorate the struct type instead (SPIR-V has this problem) - You need to compute field indices during lowering, when you might prefer to defer that until later - The get/set field operations now need an index, which needs to be an explicit operand, which means a magic numeric literal floating around to represent the index The new approach fixes for the first two of these, and at least makes the last one a bit nicer. A `StructDecl` is now a parent instruction, and its sub-instructions represent the fields of the type - each field is an explicit instruction of type `StructField`. The operation to extract a field takes a direct reference the struct field, so everything is quite explicit.
Diffstat (limited to 'source')
-rw-r--r--source/slang/emit.cpp22
-rw-r--r--source/slang/ir-inst-defs.h7
-rw-r--r--source/slang/ir.cpp32
-rw-r--r--source/slang/ir.h37
-rw-r--r--source/slang/lower-to-ir.cpp46
5 files changed, 71 insertions, 73 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 35020249b..1f0436d8a 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -4016,8 +4016,8 @@ emitDeclImpl(decl, nullptr);
emitIRInstResultDecl(context, inst);
emitIROperand(context, fieldExtract->getBase());
- emit(".field");
- emit(fieldExtract->fieldIndex);
+ emit(".");
+ emit(getName(fieldExtract->getField()));
emit(";\n");
}
break;
@@ -4087,20 +4087,16 @@ emitDeclImpl(decl, nullptr);
void emitIRStruct(
EmitContext* context,
- IRStructType* structType)
+ IRStructDecl* structType)
{
emit("struct ");
emit(getName(structType));
emit("\n{\n");
- auto fieldCount = structType->getFieldCount();
- for( UInt ff = 0; ff < fieldCount; ++ff )
- {
- auto fieldType = structType->getFieldType(ff);
-
- String fieldName = "field";
- fieldName.append(ff);
- emitIRType(context, fieldType, fieldName);
+ for(auto ff = structType->getFirstField(); ff; ff = ff->getNextField())
+ {
+ auto fieldType = ff->getFieldType();
+ emitIRType(context, fieldType, getName(ff));
emit(";\n");
}
emit("};\n");
@@ -4119,7 +4115,7 @@ emitDeclImpl(decl, nullptr);
break;
case kIROp_StructType:
- emitIRStruct(context, (IRStructType*) inst);
+ emitIRStruct(context, (IRStructDecl*) inst);
break;
default:
@@ -4254,7 +4250,7 @@ String emitEntryPoint(
//
// We'll try to detect the cases here:
//
-#if 0
+#if 1
if(!(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ))
{
// This seems to be case (3), because the user is asking for full
diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h
index 8445e5a1e..d594d2755 100644
--- a/source/slang/ir-inst-defs.h
+++ b/source/slang/ir-inst-defs.h
@@ -14,7 +14,7 @@ INST(BoolType, type.bool, 0, 0)
INST(Float32Type, type.f32, 0, 0)
INST(Int32Type, type.i32, 0, 0)
INST(UInt32Type, type.u32, 0, 0)
-INST(StructType, type.struct, 0, 0)
+INST(StructType, type.struct, 0, PARENT)
INST(FuncType, func_type, 0, 0)
INST(IntLit, integer_constant, 0, 0)
@@ -26,9 +26,10 @@ INST(Module, module, 0, PARENT)
INST(Func, func, 0, PARENT)
INST(Block, block, 0, PARENT)
-INST(Param, param, 0, 0)
+INST(Param, param, 0, 0)
+INST(StructField, field, 0, 0)
-INST(FieldExtract, get_field, 1, 0)
+INST(FieldExtract, get_field, 2, 0)
INST(ReturnVal, return_val, 1, 0)
INST(ReturnVoid, return_void, 1, 0)
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index d2c3f5ba5..b6af6aabb 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -622,20 +622,23 @@ namespace Slang
getTypeType());
}
- IRType* IRBuilder::getStructType(
- UInt fieldCount,
- IRType* const* fieldTypes)
+ IRStructDecl* IRBuilder::createStructType()
{
- auto inst = createInstWithTrailingArgs<IRStructType>(
+ return createInst<IRStructDecl>(
this,
kIROp_StructType,
- getTypeType(),
- fieldCount,
- (IRValue* const*)fieldTypes);
- addInst(inst);
- return inst;
+ getTypeType());
}
+ IRStructField* IRBuilder::createStructField(IRType* fieldType)
+ {
+ return createInst<IRStructField>(
+ this,
+ kIROp_StructField,
+ fieldType);
+ }
+
+
IRType* IRBuilder::getFuncType(
UInt paramCount,
IRType* const* paramTypes,
@@ -753,17 +756,16 @@ namespace Slang
}
IRInst* IRBuilder::emitFieldExtract(
- IRType* type,
- IRValue* base,
- UInt fieldIndex)
+ IRType* type,
+ IRValue* base,
+ IRStructField* field)
{
auto inst = createInst<IRFieldExtract>(
this,
kIROp_FieldExtract,
type,
- base);
-
- inst->fieldIndex = fieldIndex;
+ base,
+ field);
addInst(inst);
return inst;
diff --git a/source/slang/ir.h b/source/slang/ir.h
index e583997fd..319340024 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -153,13 +153,6 @@ struct IRVectorType : IRType
IRInst* getElementCount() { return elementCount.usedValue; }
};
-struct IRStructType : IRType
-{
-
- UInt getFieldCount() { return getArgCount() - 1; }
- IRType* getFieldType(UInt index) { return (IRType*) getArg(index + 1); }
-};
-
struct IRFuncType : IRType
{
IRUse resultType;
@@ -176,12 +169,14 @@ struct IRFuncType : IRType
}
};
+struct IRStructField;
struct IRFieldExtract : IRInst
{
IRUse base;
- UInt fieldIndex;
+ IRUse field;
IRInst* getBase() { return base.usedValue; }
+ IRStructField* getField() { return (IRStructField*) field.usedValue; }
};
// A instruction that ends a basic block (usually because of control flow)
@@ -212,6 +207,20 @@ struct IRParentInst : IRInst
IRInst* lastChild;
};
+struct IRStructField : IRInst
+{
+ IRType* getFieldType() { return (IRType*) type.usedValue; }
+
+ IRStructField* getNextField() { return (IRStructField*) nextInst; }
+};
+
+struct IRStructDecl : IRParentInst
+{
+ IRStructField* getFirstField() { return (IRStructField*) firstChild; }
+ IRStructField* getLastField() { return (IRStructField*) lastChild; }
+};
+
+
// A basic block is a parent instruction that adds the constraint
// that all the children need to be "ordinary" instructions (so
// no function declarations, or nested blocks). We also expect
@@ -308,9 +317,9 @@ struct IRBuilder
IRType* getTypeType();
IRType* getVoidType();
IRType* getBlockType();
- IRType* getStructType(
- UInt fieldCount,
- IRType* const* fieldTypes);
+
+ IRStructDecl* createStructType();
+ IRStructField* createStructField(IRType* fieldType);
IRType* getFuncType(
UInt paramCount,
@@ -343,9 +352,9 @@ struct IRBuilder
IRType* type);
IRInst* emitFieldExtract(
- IRType* type,
- IRValue* base,
- UInt fieldIndex);
+ IRType* type,
+ IRValue* base,
+ IRStructField* field);
IRInst* emitReturn(
IRValue* val);
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index ed8ed3318..5d0a40072 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -394,7 +394,7 @@ struct ExprLoweringVisitor : ExprVisitor<ExprLoweringVisitor, LoweredValInfo>
LoweredValInfo extractField(
LoweredTypeInfo fieldType,
LoweredValInfo base,
- UInt fieldIndex)
+ LoweredValInfo field)
{
switch (base.flavor)
{
@@ -405,7 +405,7 @@ struct ExprLoweringVisitor : ExprVisitor<ExprLoweringVisitor, LoweredValInfo>
getBuilder()->emitFieldExtract(
getSimpleType(fieldType),
irBase,
- fieldIndex));
+ (IRStructField*) getSimpleVal(field)));
}
break;
@@ -424,22 +424,8 @@ struct ExprLoweringVisitor : ExprVisitor<ExprLoweringVisitor, LoweredValInfo>
{
// Okay, easy enough: we have a reference to a field of a struct type...
- // HACK: for now just scan the decl to find the right index.
- // TODO: we need to deal with the fact that the struct might get
- // tuple-ified.
- //
- UInt index = 0;
- for (auto fieldDecl : getMembersOfType<StructField>(fieldDeclRef.GetParent().As<AggTypeDecl>()))
- {
- if (fieldDecl == fieldDeclRef.getDecl())
- {
- break;
- }
-
- index++;
- }
-
- return extractField(loweredType, loweredBase, index);
+ auto loweredField = ensureDecl(context, fieldDeclRef);
+ return extractField(loweredType, loweredBase, loweredField);
}
SLANG_UNIMPLEMENTED_X("codegen for subscript expression");
@@ -559,20 +545,27 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// User-defined aggregate type: need to translate into
// a corresponding IR aggregate type.
- List<LoweredTypeInfo> fieldTypes;
- List<IRType*> irFieldTypes;
+ auto builder = getBuilder();
+ IRStructDecl* irStruct = builder->createStructType();
for (auto fieldDecl : decl->GetFields())
{
+ // TODO: need to track relationship to original fields...
+
// TODO: need to be prepared to deal with tuple-ness of fields here
auto fieldType = lowerType(context, fieldDecl->getType());
- fieldTypes.Add(fieldType);
-
switch (fieldType.flavor)
{
case LoweredTypeInfo::Flavor::Simple:
- irFieldTypes.Add(fieldType.type);
+ {
+ auto irField = builder->createStructField(getSimpleType(fieldType));
+ builder->addInst(irStruct, irField);
+
+ context->shared->declValues.Add(
+ DeclRef<StructField>(fieldDecl, nullptr),
+ LoweredValInfo::simple(irField));
+ }
break;
default:
@@ -580,13 +573,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
}
- // TODO: need to track relationship to original fields...
- IRType* irStructType = getBuilder()->getStructType(
- irFieldTypes.Count(),
- &irFieldTypes[0]);
+ builder->addInst(irStruct);
- return LoweredValInfo::simple(irStructType);
+ return LoweredValInfo::simple(irStruct);
}
LoweredValInfo visitFunctionDeclBase(FunctionDeclBase* decl)