diff options
| author | Yong He <yonghe@outlook.com> | 2020-08-07 18:36:01 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-07 18:36:01 -0700 |
| commit | dd980b492aba9ea1540193434184489d9d04608d (patch) | |
| tree | 2974ad7462bc540729f1685ea6cf31d337f39648 | |
| parent | 20af567033dedea15abb22fb7d344d116d7b99c5 (diff) | |
AnyValue packing/unpacking pass. (#1480)
* AnyValue packing/unpacking pass.
* Add diagnostic for types that does not fit in required AnyValueSize.
* Add expected test result
* Fix warnings.
| -rw-r--r-- | prelude/slang-cpp-types.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-any-value-marshalling.cpp | 487 | ||||
| -rw-r--r-- | source/slang/slang-ir-any-value-marshalling.h | 14 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-generics.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 4 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 18 | ||||
| -rw-r--r-- | tests/diagnostics/interfaces/anyvalue-size-validation.slang | 29 | ||||
| -rw-r--r-- | tests/diagnostics/interfaces/anyvalue-size-validation.slang.expected | 6 |
11 files changed, 563 insertions, 8 deletions
diff --git a/prelude/slang-cpp-types.h b/prelude/slang-cpp-types.h index 49461e4f4..69e69f8df 100644 --- a/prelude/slang-cpp-types.h +++ b/prelude/slang-cpp-types.h @@ -41,6 +41,7 @@ struct Array size_t count; }; +#if 0 template<size_t N> struct AnyValue { @@ -60,6 +61,7 @@ T unpackAnyValue(const AnyValue<N>& val) memcpy(&result, &val, sizeof(T)); return result; } +#endif /* Constant buffers become a pointer to the contained type, so ConstantBuffer<T> becomes T* in C++ code. */ diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index ed224c30b..3e0d488f9 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -495,6 +495,7 @@ DIAGNOSTIC(41000, Warning, unreachableCode, "unreachable code detected") DIAGNOSTIC(41010, Warning, missingReturn, "control flow may reach end of non-'void' function") +DIAGNOSTIC(41011, Error, typeDoesNotFitAnyValueSize, "type '$0' does not fit in the size required by its conforming interface.") // // 5xxxx - Target code generation. // diff --git a/source/slang/slang-ir-any-value-marshalling.cpp b/source/slang/slang-ir-any-value-marshalling.cpp new file mode 100644 index 000000000..26a9fca58 --- /dev/null +++ b/source/slang/slang-ir-any-value-marshalling.cpp @@ -0,0 +1,487 @@ +#include "slang-ir-any-value-marshalling.h" + +#include "slang-ir-generics-lowering-context.h" +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + // This is a subpass of generics lowering IR transformation. + // This pass generates packing/unpacking functions for `AnyValue`s, + // and replaces all `IRPackAnyValue` and `IRUnpackAnyValue` with calls to these + // functions. + struct AnyValueMarshallingContext + { + SharedGenericsLoweringContext* sharedContext; + + // Stores information about generated `AnyValue` struct types. + struct AnyValueTypeInfo : RefObject + { + IRType* type; // The generated IR value for the `AnyValue<N>` struct type. + List<IRStructKey*> fieldKeys; // `IRStructKey`s for the fields of the generated type. + }; + + Dictionary<IRIntegerValue, RefPtr<AnyValueTypeInfo>> generatedAnyValueTypes; + + struct MarshallingFunctionKey + { + IRType* originalType; + IRIntegerValue anyValueSize; + bool operator ==(MarshallingFunctionKey other) + { + return originalType == other.originalType && anyValueSize == other.anyValueSize; + } + HashCode getHashCode() const + { + return combineHash(Slang::getHashCode(originalType), Slang::getHashCode(anyValueSize)); + } + }; + + struct MarshallingFunctionSet + { + IRFunc* packFunc; + IRFunc* unpackFunc; + }; + + // Stores the generated packing/unpacking functions for lookup. + Dictionary<MarshallingFunctionKey, MarshallingFunctionSet> mapTypeMarshalingFunctions; + + AnyValueTypeInfo* ensureAnyValueType(IRAnyValueType* type) + { + auto size = getIntVal(type->getSize()); + if (auto typeInfo = generatedAnyValueTypes.TryGetValue(size)) + return typeInfo->Ptr(); + RefPtr<AnyValueTypeInfo> info = new AnyValueTypeInfo(); + IRBuilder builder; + builder.sharedBuilder = &sharedContext->sharedBuilderStorage; + builder.setInsertBefore(type); + auto structType = builder.createStructType(); + info->type = structType; + StringBuilder nameSb; + nameSb << "AnyValue" << size; + builder.addExportDecoration(structType, nameSb.getUnownedSlice()); + auto fieldCount = (size + sizeof(uint32_t) - 1) / sizeof(uint32_t); + for (decltype(fieldCount) i = 0; i < fieldCount; i++) + { + auto key = builder.createStructKey(); + nameSb.Clear(); + nameSb << "field" << i; + builder.addNameHintDecoration(key, nameSb.getUnownedSlice()); + nameSb << "_anyVal" << size; + builder.addExportDecoration(key, nameSb.getUnownedSlice()); + builder.createStructField(structType, key, builder.getUIntType()); + info->fieldKeys.add(key); + } + generatedAnyValueTypes[size] = info; + return info.Ptr(); + } + + struct TypeMarshallingContext + { + AnyValueTypeInfo* anyValInfo; + uint32_t fieldOffset; + uint32_t intraFieldOffset; + IRType* uintPtrType; + IRInst* anyValueVar; + // Defines what to do with basic typed data elements. + virtual void marshalBasicType(IRBuilder* builder, IRType* dataType, IRInst* concreteTypedVar) = 0; + + // Validates that the type fits in the given AnyValueSize. + // After calling emitMarshallingCode, `fieldOffset` will be increased to the required `AnyValue` size. + // If this is larger than the provided AnyValue size, report a dianogstic. We might want to front load + // this in a separate IR validation pass in the future, but this is the easiest way to report the + // diagnostic now. + void validateAnyTypeSize(DiagnosticSink* sink, IRType* concreteType) + { + if (fieldOffset > static_cast<uint32_t>(anyValInfo->fieldKeys.getCount())) + { + sink->diagnose(concreteType->sourceLoc, Diagnostics::typeDoesNotFitAnyValueSize, concreteType); + } + } + }; + + void emitMarshallingCode( + IRBuilder* builder, + TypeMarshallingContext* context, + IRInst* concreteTypedVar) + { + auto dataType = cast<IRPtrTypeBase>(concreteTypedVar->getDataType())->getValueType(); + switch (dataType->op) + { + case kIROp_IntType: + case kIROp_FloatType: + case kIROp_UIntType: + case kIROp_UInt64Type: + case kIROp_Int64Type: + case kIROp_DoubleType: + case kIROp_Int8Type: + case kIROp_Int16Type: + case kIROp_UInt8Type: + case kIROp_UInt16Type: + case kIROp_HalfType: + context->marshalBasicType(builder, dataType, concreteTypedVar); + break; + case kIROp_VectorType: + { + auto vectorType = static_cast<IRVectorType*>(dataType); + auto elementType = vectorType->getElementType(); + auto elementCount = getIntVal(vectorType->getElementCount()); + for (IRIntegerValue i = 0; i < elementCount; i++) + { + auto elementVal = builder->emitElementExtract( + elementType, + concreteTypedVar, + builder->getIntValue(builder->getIntType(), i)); + emitMarshallingCode(builder, context, elementVal); + } + break; + } + case kIROp_MatrixType: + { + auto matrixType = static_cast<IRMatrixType*>(dataType); + auto elementType = matrixType->getElementType(); + auto colCount = getIntVal(matrixType->getColumnCount()); + auto rowCount = getIntVal(matrixType->getRowCount()); + for (IRIntegerValue i = 0; i < colCount; i++) + { + auto col = builder->emitElementAddress( + elementType, + concreteTypedVar, + builder->getIntValue(builder->getIntType(), i)); + for (IRIntegerValue j = 0; j < rowCount; j++) + { + auto element = builder->emitElementExtract( + elementType, + col, + builder->getIntValue(builder->getIntType(), i)); + emitMarshallingCode(builder, context, element); + } + } + break; + } + case kIROp_StructType: + { + auto structType = cast<IRStructType>(dataType); + for (auto field : structType->getFields()) + { + auto fieldAddr = builder->emitFieldAddress( + builder->getPtrType(field->getFieldType()), + concreteTypedVar, + field->getKey()); + emitMarshallingCode(builder, context, fieldAddr); + } + break; + } + case kIROp_ArrayType: + { + auto arrayType = cast<IRArrayType>(dataType); + auto elementPtrType = builder->getPtrType(arrayType->getElementType()); + for (IRIntegerValue i = 0; i < getIntVal(arrayType->getElementCount()); i++) + { + auto fieldAddr = builder->emitElementAddress( + elementPtrType, + concreteTypedVar, + builder->getIntValue(builder->getIntType(), i)); + emitMarshallingCode(builder, context, fieldAddr); + } + break; + } + default: + SLANG_UNIMPLEMENTED_X("Unimplemented type packing"); + break; + } + } + + struct TypePackingContext : TypeMarshallingContext + { + virtual void marshalBasicType(IRBuilder* builder, IRType* dataType, IRInst* concreteVar) override + { + switch (dataType->op) + { + case kIROp_IntType: + case kIROp_FloatType: + { + if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount())) + { + auto srcVal = builder->emitLoad(concreteVar); + auto dstVal = builder->emitBitCast(builder->getUIntType(), srcVal); + auto dstAddr = builder->emitFieldAddress( + uintPtrType, + anyValueVar, + anyValInfo->fieldKeys[fieldOffset]); + builder->emitStore(dstAddr, dstVal); + } + fieldOffset++; + break; + } + case kIROp_UIntType: + { + if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount())) + { + auto srcVal = builder->emitLoad(concreteVar); + auto dstAddr = builder->emitFieldAddress( + uintPtrType, + anyValueVar, + anyValInfo->fieldKeys[fieldOffset]); + builder->emitStore(dstAddr, srcVal); + } + fieldOffset++; + break; + } + case kIROp_UInt64Type: + case kIROp_Int64Type: + case kIROp_DoubleType: + case kIROp_Int8Type: + case kIROp_Int16Type: + case kIROp_UInt8Type: + case kIROp_UInt16Type: + case kIROp_HalfType: + SLANG_UNIMPLEMENTED_X("AnyValue type packing for non 32-bit elements"); + break; + default: + SLANG_UNREACHABLE("unknown basic type"); + } + } + }; + + IRFunc* generatePackingFunc(IRType* type, IRAnyValueType* anyValueType) + { + IRBuilder builder; + builder.sharedBuilder = &sharedContext->sharedBuilderStorage; + builder.setInsertBefore(type); + auto anyValInfo = ensureAnyValueType(anyValueType); + + auto func = builder.createFunc(); + + StringBuilder nameSb; + nameSb << "packAnyValue" << getIntVal(anyValueType->getSize()); + builder.addNameHintDecoration(func, nameSb.getUnownedSlice()); + // Currently we don't add linkage to the generated func, since we + // do not have a way to compute mangled names from an IR entity. + // This will leads to duplicate packing functions in linked code + // but there won't be correctness issues. + + auto funcType = builder.getFuncType(1, &type, anyValInfo->type); + func->setFullType(funcType); + builder.setInsertInto(func); + + builder.emitBlock(); + + auto param = builder.emitParam(type); + auto concreteTypedVar = builder.emitVar(type); + builder.emitStore(concreteTypedVar, param); + auto resultVar = builder.emitVar(anyValInfo->type); + + TypePackingContext context; + context.anyValInfo = anyValInfo; + context.fieldOffset = context.intraFieldOffset = 0; + context.uintPtrType = builder.getPtrType(builder.getUIntType()); + context.anyValueVar = resultVar; + emitMarshallingCode(&builder, &context, concreteTypedVar); + context.validateAnyTypeSize(sharedContext->sink, type); + auto load = builder.emitLoad(resultVar); + builder.emitReturn(load); + return func; + } + + struct TypeUnpackingContext : TypeMarshallingContext + { + virtual void marshalBasicType(IRBuilder* builder, IRType* dataType, IRInst* concreteVar) override + { + switch (dataType->op) + { + case kIROp_IntType: + case kIROp_FloatType: + { + if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount())) + { + auto srcAddr = builder->emitFieldAddress( + uintPtrType, + anyValueVar, + anyValInfo->fieldKeys[fieldOffset]); + auto srcVal = builder->emitLoad(srcAddr); + srcVal = builder->emitBitCast(dataType, srcVal); + builder->emitStore(concreteVar, srcVal); + } + fieldOffset++; + break; + } + case kIROp_UIntType: + { + if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount())) + { + auto srcAddr = builder->emitFieldAddress( + uintPtrType, + anyValueVar, + anyValInfo->fieldKeys[fieldOffset]); + auto srcVal = builder->emitLoad(srcAddr); + builder->emitStore(concreteVar, srcVal); + } + fieldOffset++; + break; + } + case kIROp_UInt64Type: + case kIROp_Int64Type: + case kIROp_DoubleType: + case kIROp_Int8Type: + case kIROp_Int16Type: + case kIROp_UInt8Type: + case kIROp_UInt16Type: + case kIROp_HalfType: + SLANG_UNIMPLEMENTED_X("AnyValue type packing for non 32-bit elements"); + break; + default: + SLANG_UNREACHABLE("unknown basic type"); + } + } + }; + + IRFunc* generateUnpackingFunc(IRType* type, IRAnyValueType* anyValueType) + { + IRBuilder builder; + builder.sharedBuilder = &sharedContext->sharedBuilderStorage; + builder.setInsertBefore(type); + auto anyValInfo = ensureAnyValueType(anyValueType); + + auto func = builder.createFunc(); + + StringBuilder nameSb; + nameSb << "unpackAnyValue" << getIntVal(anyValueType->getSize()); + builder.addNameHintDecoration(func, nameSb.getUnownedSlice()); + + auto funcType = builder.getFuncType(1, &anyValInfo->type, type); + func->setFullType(funcType); + builder.setInsertInto(func); + + builder.emitBlock(); + + auto param = builder.emitParam(anyValInfo->type); + auto anyValueVar = builder.emitVar(anyValInfo->type); + builder.emitStore(anyValueVar, param); + auto resultVar = builder.emitVar(type); + + TypeUnpackingContext context; + context.anyValInfo = anyValInfo; + context.fieldOffset = context.intraFieldOffset = 0; + context.uintPtrType = builder.getPtrType(builder.getUIntType()); + context.anyValueVar = anyValueVar; + emitMarshallingCode(&builder, &context, resultVar); + auto load = builder.emitLoad(resultVar); + builder.emitReturn(load); + return func; + } + + // Ensures the marshalling functions between `type` and `anyValueType` are already generated. + // Returns the generated marshalling functions. + MarshallingFunctionSet ensureMarshallingFunc(IRType* type, IRAnyValueType* anyValueType) + { + auto size = getIntVal(anyValueType->getSize()); + MarshallingFunctionKey key; + key.originalType = type; + key.anyValueSize = size; + MarshallingFunctionSet funcSet; + if (mapTypeMarshalingFunctions.TryGetValue(key, funcSet)) + return funcSet; + funcSet.packFunc = generatePackingFunc(type, anyValueType); + funcSet.unpackFunc = generateUnpackingFunc(type, anyValueType); + mapTypeMarshalingFunctions[key] = funcSet; + return funcSet; + } + + void processPackInst(IRPackAnyValue* packInst) + { + auto operand = packInst->getValue(); + auto func = ensureMarshallingFunc( + operand->getDataType(), + cast<IRAnyValueType>(packInst->getDataType())); + IRBuilder builderStorage; + auto builder = &builderStorage; + builder->sharedBuilder = &sharedContext->sharedBuilderStorage; + builder->setInsertBefore(packInst); + auto callInst = builder->emitCallInst(packInst->getDataType(), func.packFunc, 1, &operand); + packInst->replaceUsesWith(callInst); + packInst->removeAndDeallocate(); + } + + void processUnpackInst(IRUnpackAnyValue* unpackInst) + { + auto operand = unpackInst->getValue(); + auto func = ensureMarshallingFunc( + unpackInst->getDataType(), + cast<IRAnyValueType>(operand->getDataType())); + IRBuilder builderStorage; + auto builder = &builderStorage; + builder->sharedBuilder = &sharedContext->sharedBuilderStorage; + builder->setInsertBefore(unpackInst); + auto callInst = builder->emitCallInst(unpackInst->getDataType(), func.unpackFunc, 1, &operand); + unpackInst->replaceUsesWith(callInst); + unpackInst->removeAndDeallocate(); + } + + void processAnyValueType(IRAnyValueType* type) + { + auto info = ensureAnyValueType(type); + type->replaceUsesWith(info->type); + } + + void processInst(IRInst* inst) + { + if (auto packInst = as<IRPackAnyValue>(inst)) + { + processPackInst(packInst); + } + else if (auto unpackInst = as<IRUnpackAnyValue>(inst)) + { + processUnpackInst(unpackInst); + } + } + + void processModule() + { + // We start by initializing our shared IR building state, + // since we will re-use that state for any code we + // generate along the way. + // + SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage; + sharedBuilder->module = sharedContext->module; + sharedBuilder->session = sharedContext->module->session; + + sharedContext->addToWorkList(sharedContext->module->getModuleInst()); + + // Process all instructions and translate all `IRPackAnyValue` and `IRUnpackAnyValue`. + while (sharedContext->workList.getCount() != 0) + { + // We will then iterate until our work list goes dry. + // + while (sharedContext->workList.getCount() != 0) + { + IRInst* inst = sharedContext->workList.getLast(); + + sharedContext->workList.removeLast(); + sharedContext->workListSet.Remove(inst); + + processInst(inst); + + for (auto child = inst->getLastChild(); child; child = child->getPrevInst()) + { + sharedContext->addToWorkList(child); + } + } + } + + // Finally, replace all `AnyValueType` with the actual struct type that implements it. + for (auto inst : sharedContext->module->getModuleInst()->getChildren()) + { + if (auto anyValueType = as<IRAnyValueType>(inst)) + processAnyValueType(anyValueType); + } + } + }; + + void generateAnyValueMarshallingFunctions(SharedGenericsLoweringContext* sharedContext) + { + AnyValueMarshallingContext context; + context.sharedContext = sharedContext; + context.processModule(); + } +} diff --git a/source/slang/slang-ir-any-value-marshalling.h b/source/slang/slang-ir-any-value-marshalling.h new file mode 100644 index 000000000..943b61aa3 --- /dev/null +++ b/source/slang/slang-ir-any-value-marshalling.h @@ -0,0 +1,14 @@ +// slang-ir-any-value-marshalling.h +#pragma once + +namespace Slang +{ + struct SharedGenericsLoweringContext; + + /// Generates functions that pack and unpack `AnyValue`s, and replaces + /// all `IRPackAnyValue` and `IRUnpackAnyValue` instructions with calls + /// to these packing/unpacking functions. + /// This is a sub-pass of lower-generics. + void generateAnyValueMarshallingFunctions( + SharedGenericsLoweringContext* sharedContext); +} diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index cd2babfa6..e022b353c 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -1693,6 +1693,7 @@ struct IRBuilder IRBasicType* getVoidType(); IRBasicType* getBoolType(); IRBasicType* getIntType(); + IRBasicType* getUIntType(); IRStringType* getStringType(); IRAssociatedType* getAssociatedType(ArrayView<IRInterfaceType*> constraintTypes); IRThisType* getThisType(IRInterfaceType* interfaceType); diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp index 9960b7451..7df590b23 100644 --- a/source/slang/slang-ir-lower-generics.cpp +++ b/source/slang/slang-ir-lower-generics.cpp @@ -1,6 +1,7 @@ // slang-ir-lower-generics.cpp #include "slang-ir-lower-generics.h" +#include "slang-ir-any-value-marshalling.h" #include "slang-ir-generics-lowering-context.h" #include "slang-ir-lower-generic-function.h" #include "slang-ir-lower-generic-call.h" @@ -22,10 +23,11 @@ namespace Slang lowerGenericFunctions(&sharedContext); lowerGenericType(&sharedContext); lowerGenericCalls(&sharedContext); + generateWitnessTableWrapperFunctions(&sharedContext); + generateAnyValueMarshallingFunctions(&sharedContext); // We might have generated new temporary variables during lowering. // An SSA pass can clean up unnecessary load/stores. constructSSA(module); eliminateDeadCode(module); - generateWitnessTableWrapperFunctions(&sharedContext); } } // namespace Slang diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 2c9aee817..1a6187a92 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -2222,6 +2222,11 @@ namespace Slang return (IRBasicType*)getType(kIROp_IntType); } + IRBasicType* IRBuilder::getUIntType() + { + return (IRBasicType*)getType(kIROp_UIntType); + } + IRStringType* IRBuilder::getStringType() { return (IRStringType*)getType(kIROp_StringType); diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index 8df498a11..97f4bba25 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -221,6 +221,7 @@ <ClInclude Include="slang-glsl-extension-tracker.h" /> <ClInclude Include="slang-hlsl-intrinsic-set.h" /> <ClInclude Include="slang-image-format-defs.h" /> + <ClInclude Include="slang-ir-any-value-marshalling.h" /> <ClInclude Include="slang-ir-bind-existentials.h" /> <ClInclude Include="slang-ir-byte-address-legalize.h" /> <ClInclude Include="slang-ir-clone.h" /> @@ -323,6 +324,7 @@ <ClCompile Include="slang-file-system.cpp" /> <ClCompile Include="slang-glsl-extension-tracker.cpp" /> <ClCompile Include="slang-hlsl-intrinsic-set.cpp" /> + <ClCompile Include="slang-ir-any-value-marshalling.cpp" /> <ClCompile Include="slang-ir-bind-existentials.cpp" /> <ClCompile Include="slang-ir-byte-address-legalize.cpp" /> <ClCompile Include="slang-ir-clone.cpp" /> @@ -404,4 +406,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project>
\ No newline at end of file +</Project>
\ No newline at end of file diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index 6e0a4b80b..679e773d0 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -114,6 +114,9 @@ <ClInclude Include="slang-image-format-defs.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-ir-any-value-marshalling.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="slang-ir-bind-existentials.h"> <Filter>Header Files</Filter> </ClInclude> @@ -177,6 +180,9 @@ <ClInclude Include="slang-ir-lower-generic-function.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-ir-lower-generic-type.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="slang-ir-lower-generics.h"> <Filter>Header Files</Filter> </ClInclude> @@ -309,9 +315,6 @@ <ClInclude Include="slang-visitor.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="slang-ir-lower-generic-type.h"> - <Filter>Header Files</Filter> - </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="slang-ast-builder.cpp"> @@ -416,6 +419,9 @@ <ClCompile Include="slang-hlsl-intrinsic-set.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="slang-ir-any-value-marshalling.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="slang-ir-bind-existentials.cpp"> <Filter>Source Files</Filter> </ClCompile> @@ -476,6 +482,9 @@ <ClCompile Include="slang-ir-lower-generic-function.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="slang-ir-lower-generic-type.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="slang-ir-lower-generics.cpp"> <Filter>Source Files</Filter> </ClCompile> @@ -605,9 +614,6 @@ <ClCompile Include="slang.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="slang-ir-lower-generic-type.cpp"> - <Filter>Source Files</Filter> - </ClCompile> </ItemGroup> <ItemGroup> <None Include="core.meta.slang"> diff --git a/tests/diagnostics/interfaces/anyvalue-size-validation.slang b/tests/diagnostics/interfaces/anyvalue-size-validation.slang new file mode 100644 index 000000000..b7cd5ba34 --- /dev/null +++ b/tests/diagnostics/interfaces/anyvalue-size-validation.slang @@ -0,0 +1,29 @@ +// anyvalue-size-validation.slang + +//DIAGNOSTIC_TEST:SIMPLE:-target cpp -stage compute -entry main -allow-dynamic-code + +[anyValueSize(8)] +interface IInterface +{ + int doSomething(); +}; + +struct S : IInterface +{ + uint a; + uint b; + uint c; + int doSomething() { return 5; } +}; + +T test<T:IInterface>(T s) +{ + return s; +} + +[numthreads(4, 1, 1)] +void main() +{ + S s; + test(s); +}
\ No newline at end of file diff --git a/tests/diagnostics/interfaces/anyvalue-size-validation.slang.expected b/tests/diagnostics/interfaces/anyvalue-size-validation.slang.expected new file mode 100644 index 000000000..e88b6bd5d --- /dev/null +++ b/tests/diagnostics/interfaces/anyvalue-size-validation.slang.expected @@ -0,0 +1,6 @@ +result code = -1 +standard error = { +tests/diagnostics/interfaces/anyvalue-size-validation.slang(11): error 41011: type 'S' does not fit in the size required by its conforming interface. +} +standard output = { +} |
