diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/hlsl.meta.slang | 2 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 4 | ||||
| -rw-r--r-- | source/slang/ir-legalize-types.cpp | 66 | ||||
| -rw-r--r-- | source/slang/ir-specialize.cpp | 48 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 71 | ||||
| -rw-r--r-- | source/slang/ir.h | 8 |
6 files changed, 131 insertions, 68 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 4044600aa..a12e45c36 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -1036,10 +1036,12 @@ __generic<let N : int> float noise(vector<float, N> x); /// is more semantically "correct." __target_intrinsic(glsl, nonuniformEXT) __glsl_extension(GL_EXT_nonuniform_qualifier) +[__readNone] uint NonUniformResourceIndex(uint index); __target_intrinsic(glsl, nonuniformEXT) __glsl_extension(GL_EXT_nonuniform_qualifier) +[__readNone] int NonUniformResourceIndex(int index); // Normalize a vector diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h index 1342badb8..a82a733ac 100644 --- a/source/slang/hlsl.meta.slang.h +++ b/source/slang/hlsl.meta.slang.h @@ -1112,10 +1112,12 @@ SLANG_RAW("/// the user's responsibility, so that the default behavior of the la SLANG_RAW("/// is more semantically \"correct.\"\n") SLANG_RAW("__target_intrinsic(glsl, nonuniformEXT)\n") SLANG_RAW("__glsl_extension(GL_EXT_nonuniform_qualifier)\n") +SLANG_RAW("[__readNone]\n") SLANG_RAW("uint NonUniformResourceIndex(uint index);\n") SLANG_RAW("\n") SLANG_RAW("__target_intrinsic(glsl, nonuniformEXT)\n") SLANG_RAW("__glsl_extension(GL_EXT_nonuniform_qualifier)\n") +SLANG_RAW("[__readNone]\n") SLANG_RAW("int NonUniformResourceIndex(int index);\n") SLANG_RAW("\n") SLANG_RAW("// Normalize a vector\n") @@ -1529,7 +1531,7 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) sb << "};\n"; } -SLANG_RAW("#line 1456 \"hlsl.meta.slang\"") +SLANG_RAW("#line 1458 \"hlsl.meta.slang\"") SLANG_RAW("\n") SLANG_RAW("\n") SLANG_RAW("\n") diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp index 0c1465fb4..00b8109ee 100644 --- a/source/slang/ir-legalize-types.cpp +++ b/source/slang/ir-legalize-types.cpp @@ -560,6 +560,60 @@ static LegalVal wrapBufferValue( } } +static IRType* getPointedToType( + IRTypeLegalizationContext* context, + IRType* ptrType) +{ + auto valueType = tryGetPointedToType(context->builder, ptrType); + if( !valueType ) + { + SLANG_UNEXPECTED("expected a pointer type during type legalization"); + } + return valueType; +} + +static LegalType getPointedToType( + IRTypeLegalizationContext* context, + LegalType type) +{ + switch( type.flavor ) + { + case LegalType::Flavor::none: + return LegalType(); + + case LegalType::Flavor::simple: + return LegalType::simple(getPointedToType(context, type.getSimple())); + + case LegalType::Flavor::implicitDeref: + return type.getImplicitDeref()->valueType; + + case LegalType::Flavor::pair: + { + auto pairType = type.getPair(); + auto ordinary = getPointedToType(context, pairType->ordinaryType); + auto special = getPointedToType(context, pairType->specialType); + return LegalType::pair(ordinary, special, pairType->pairInfo); + } + + case LegalType::Flavor::tuple: + { + auto tupleType = type.getTuple(); + RefPtr<TuplePseudoType> resultTuple = new TuplePseudoType(); + for( auto ee : tupleType->elements ) + { + TuplePseudoType::Element resultElement; + resultElement.key = ee.key; + resultElement.type = getPointedToType(context, ee.type); + } + return LegalType::tuple(resultTuple); + } + + default: + SLANG_UNEXPECTED("unhandled case in type legalization"); + UNREACHABLE_RETURN(LegalType()); + } +} + static LegalVal legalizeFieldAddress( IRTypeLegalizationContext* context, LegalType type, @@ -678,8 +732,8 @@ static LegalVal legalizeFieldAddress( // adding an implicit dereference on top of that. // auto implicitDerefVal = legalPtrOperand.getImplicitDeref(); - - return LegalVal::implicitDeref(legalizeFieldExtract(context,type, implicitDerefVal, fieldKey)); + auto valueType = getPointedToType(context, type); + return LegalVal::implicitDeref(legalizeFieldExtract(context, valueType, implicitDerefVal, fieldKey)); } default: @@ -816,7 +870,6 @@ static LegalVal legalizeGetElement( indexOperand); } - static LegalVal legalizeGetElementPtr( IRTypeLegalizationContext* context, LegalType type, @@ -914,10 +967,15 @@ static LegalVal legalizeGetElementPtr( // instead (and then wrap the element value with an // implicit dereference). // + // The result type for our `getElement` instruction needs + // to be the type *pointed to* by `type`, and not `type. + // + auto valueType = getPointedToType(context, type); + auto implicitDerefVal = legalPtrOperand.getImplicitDeref(); return LegalVal::implicitDeref(legalizeGetElement( context, - type, + valueType, implicitDerefVal, indexOperand)); } diff --git a/source/slang/ir-specialize.cpp b/source/slang/ir-specialize.cpp index 7a129a03b..e491eaa31 100644 --- a/source/slang/ir-specialize.cpp +++ b/source/slang/ir-specialize.cpp @@ -1153,54 +1153,6 @@ struct SpecializationContext } } - /// Given a type being used as pointer, try to determine the type it points to. - IRType* tryGetPointedToType( - IRBuilder* builder, - IRType* type) - { - // The "true" pointers and the pointer-like stdlib types are the easy cases. - if( auto ptrType = as<IRPtrTypeBase>(type) ) - { - return ptrType->getValueType(); - } - else if( auto ptrLikeType = as<IRPointerLikeType>(type) ) - { - return ptrLikeType->getElementType(); - } - // - // A more interesting case arises when we have a `BindExistentials<P<T>, ...>` - // where `P<T>` is a pointer(-like) type. - // - else if( auto bindExistentials = as<IRBindExistentialsType>(type) ) - { - // We know that `BindExistentials` won't introduce its own - // existential type parameters, nor will any of the pointer(-like) - // type constructors `P`. - // - // Thus we know that the type that is pointed to should be - // the same as `BindExistentials<T, ...>`. - // - auto baseType = bindExistentials->getBaseType(); - if( auto baseElementType = tryGetPointedToType(builder, baseType) ) - { - UInt existentialArgCount = bindExistentials->getExistentialArgCount(); - List<IRInst*> existentialArgs; - for( UInt ii = 0; ii < existentialArgCount; ++ii ) - { - existentialArgs.Add(bindExistentials->getExistentialArg(ii)); - } - return builder->getBindExistentialsType( - baseElementType, - existentialArgCount, - existentialArgs.Buffer()); - } - } - - // TODO: We may need to handle other cases here. - - return nullptr; - } - void maybeSpecializeLoad(IRLoad* inst) { auto ptrArg = inst->ptr.get(); diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 677429e32..3f6f8e0a3 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -236,6 +236,60 @@ namespace Slang return nullptr; } + // IRPtrTypeBase + + IRType* tryGetPointedToType( + IRBuilder* builder, + IRType* type) + { + if( auto rateQualType = as<IRRateQualifiedType>(type) ) + { + type = rateQualType->getDataType(); + } + + // The "true" pointers and the pointer-like stdlib types are the easy cases. + if( auto ptrType = as<IRPtrTypeBase>(type) ) + { + return ptrType->getValueType(); + } + else if( auto ptrLikeType = as<IRPointerLikeType>(type) ) + { + return ptrLikeType->getElementType(); + } + // + // A more interesting case arises when we have a `BindExistentials<P<T>, ...>` + // where `P<T>` is a pointer(-like) type. + // + else if( auto bindExistentials = as<IRBindExistentialsType>(type) ) + { + // We know that `BindExistentials` won't introduce its own + // existential type parameters, nor will any of the pointer(-like) + // type constructors `P`. + // + // Thus we know that the type that is pointed to should be + // the same as `BindExistentials<T, ...>`. + // + auto baseType = bindExistentials->getBaseType(); + if( auto baseElementType = tryGetPointedToType(builder, baseType) ) + { + UInt existentialArgCount = bindExistentials->getExistentialArgCount(); + List<IRInst*> existentialArgs; + for( UInt ii = 0; ii < existentialArgCount; ++ii ) + { + existentialArgs.Add(bindExistentials->getExistentialArg(ii)); + } + return builder->getBindExistentialsType( + baseElementType, + existentialArgCount, + existentialArgs.Buffer()); + } + } + + // TODO: We may need to handle other cases here. + + return nullptr; + } + // IRBlock @@ -2395,21 +2449,8 @@ namespace Slang // results) at the "default" rate of the parent function, // unless a subsequent analysis pass constraints it. - IRType* valueType = nullptr; - if(auto ptrType = as<IRPtrTypeBase>(ptr->getDataType())) - { - valueType = ptrType->getValueType(); - } - else if(auto ptrLikeType = as<IRPointerLikeType>(ptr->getDataType())) - { - valueType = ptrLikeType->getElementType(); - } - else - { - // Bad! - SLANG_ASSERT(ptrType); - return nullptr; - } + IRType* valueType = tryGetPointedToType(this, ptr->getFullType()); + SLANG_ASSERT(valueType); // Ugly special case: if the front-end created a variable with // type `Ptr<@R T>` instead of `@R Ptr<T>`, then the above diff --git a/source/slang/ir.h b/source/slang/ir.h index 09013fe48..d4497ec91 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -25,6 +25,7 @@ class Layout; class Type; class Session; class Name; +struct IRBuilder; struct IRFunc; struct IRGlobalValueWithCode; struct IRInst; @@ -934,6 +935,13 @@ SIMPLE_IR_TYPE(OutType, OutTypeBase) SIMPLE_IR_TYPE(InOutType, OutTypeBase) SIMPLE_IR_TYPE(ExistentialBoxType, PtrTypeBase) + /// Get the type pointed to be `ptrType`, or `nullptr` if it is not a pointer(-like) type. + /// + /// The given IR `builder` will be used if new instructions need to be created. +IRType* tryGetPointedToType( + IRBuilder* builder, + IRType* type); + struct IRFuncType : IRType { IRType* getResultType() { return (IRType*) getOperand(0); } |
