Переглянути джерело

First working order of binary expression type detection support.
Still incomplete because of vector/matrix combination cases.

Signed-off-by: Vivien Oddou <[email protected]>

Vivien Oddou 2 роки тому
батько
коміт
d3d742f7ff

+ 1 - 1
src/AzslcIntermediateRepresentation.cpp

@@ -518,7 +518,7 @@ namespace AZ::ShaderCompiler
             if (varInfo.GetTypeClass() == TypeClass::Enum)
             {
                 auto* asClassInfo = GetSymbolSubAs<ClassInfo>(varInfo.GetTypeId().GetName());
-                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.GetBaseSize();
+                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.m_baseSize;
             }
 
             nextMemberStartingOffset = Packing::PackNextChunk(layoutPacking, size, startAt);

+ 1 - 1
src/AzslcKindInfo.h

@@ -248,7 +248,7 @@ namespace AZ::ShaderCompiler
         //! Get the size of a single element, ignoring array dimensions
         const uint32_t GetSingleElementSize(Packing::Layout layout, bool defaultRowMajor) const
         {
-            auto baseSize = m_coreType.m_arithmeticInfo.GetBaseSize();
+            auto baseSize = m_coreType.m_arithmeticInfo.m_baseSize;
             bool isRowMajor = (m_mtxMajor == Packing::MatrixMajor::RowMajor ||
                               (m_mtxMajor == Packing::MatrixMajor::Default && defaultRowMajor));
             auto rows = m_coreType.m_arithmeticInfo.m_rows;

+ 1 - 2
src/AzslcMain.cpp

@@ -23,8 +23,7 @@ namespace StdFs = std::filesystem;
 // For large features or milestones. Minor version allows for breaking changes. Existing tests can change.
 #define AZSLC_MINOR "8"   // last change: introduction of class inheritance
 // For small features or bug fixes. They cannot introduce breaking changes. Existing tests shouldn't change.
-#define AZSLC_REVISION "17"  // last change: automatic option ranks
-                    // "16"          change: fixup runtime error with redundant function declarations
+#define AZSLC_REVISION "18"  // last change: automatic option ranks
 
 namespace AZ::ShaderCompiler
 {

+ 1 - 1
src/AzslcReflection.cpp

@@ -589,7 +589,7 @@ namespace AZ::ShaderCompiler
             else if (varInfo.GetTypeClass() == TypeClass::Enum)
             {
                 auto* asClassInfo = m_ir->GetSymbolSubAs<ClassInfo>(varInfo.GetTypeId().GetName());
-                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.GetBaseSize();
+                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.m_baseSize;
             }
 
             offset = Packing::PackNextChunk(layoutPacking, size, startAt);

+ 20 - 2
src/AzslcSemanticOrchestrator.cpp

@@ -1168,7 +1168,8 @@ namespace AZ::ShaderCompiler
                                      As<azslParser::LiteralExpressionContext*>(ctx),
                                      As<azslParser::LiteralContext*>(ctx),
                                      As<azslParser::PrefixUnaryExpressionContext*>(ctx),
-                                     As<azslParser::PostfixUnaryExpressionContext*>(ctx));
+                                     As<azslParser::PostfixUnaryExpressionContext*>(ctx),
+                                     As<azslParser::BinaryExpressionContext*>(ctx));
         }
         catch (AllNull&)
         {
@@ -1192,7 +1193,24 @@ namespace AZ::ShaderCompiler
 
     QualifiedName SemanticOrchestrator::TypeofExpr(azslParser::BinaryExpressionContext* ctx) const
     {
-        return TypeofExpr(ctx->Expr);
+        using lex = azslLexer;
+        auto boolResultOperators = {lex::Less, lex::Greater, lex::LessEqual, lex::GreaterEqual, lex::NotEqual, lex::AndAnd, lex::OrOr};
+        if (IsIn(ctx->binaryOperator()->start->getType(), boolResultOperators))
+        {
+            return MangleScalarType("bool");
+        }
+        QualifiedName lhs = TypeofExpr(ctx->Left);
+        QualifiedName rhs = TypeofExpr(ctx->Right);
+        TypeRefInfo typeInfoLhs = CreateTypeRefInfo(UnqualifiedNameView{lhs});  // We tolerate a cast here because GetTypeRefInfo was designed to lookup types, but TypeofExpr has already looked up the type.
+        TypeRefInfo typeInfoRhs = CreateTypeRefInfo(UnqualifiedNameView{rhs});
+        if (typeInfoLhs.m_arithmeticInfo.IsEmpty() || typeInfoRhs.m_arithmeticInfo.IsEmpty())
+        {   // Case that shouldn't work in AZSL yet (but may work in HLSL2021)
+            // -> UDT operator. need operator overloading. We assume type is type of left expression.
+            return lhs;
+        }
+        // final logic in case of arithmetic type class: integer/float promotion.
+        return typeInfoLhs.m_arithmeticInfo.m_conversionRank > typeInfoRhs.m_arithmeticInfo.m_conversionRank ?
+            lhs : rhs;
     }
 
     QualifiedName SemanticOrchestrator::TypeofExpr(azslParser::ExpressionExtContext* ctx) const

+ 40 - 3
src/AzslcTypes.h

@@ -281,9 +281,46 @@ namespace AZ::ShaderCompiler
         void ResolveBaseSizeAndRank()
         {
             m_baseSize = Packing::PackedSizeof(m_underlyingScalar);
-
-            
-            
+            // establish the conversion rank:
+            auto getIndex = [](string_view s) -> int
+            {
+                auto const& Scalars = Predefined::Scalar;
+                return ::std::distance(Scalars.begin(),
+                                       ::std::find(Scalars.begin(), Scalars.end(), s));
+            };
+            // According to https://en.cppreference.com/w/cpp/language/usual_arithmetic_conversions
+            //   - No two signed have the same rank (even if same siezeof)
+            //   - rank of unsigned = rank of corresponding signed
+            //   - "standard" is > "extended" of same sizeof
+            //   - The rank of bool is the smallest
+            // That said, we will take inspiration from ASTContext::getIntegerRank of clang
+            // (which does not respect C++ visibly, since it takes bool's size into account, or has many equivalent ranks, in violation of rule 1)
+            static const unordered_map<int, int> subranks =
+            {
+                {getIndex("bool"), 1},
+                {getIndex("int16_t"), 2},
+                {getIndex("uint16_t"), 3}, // unsigned wins in case of subrank draw, according to arithmetic conversion rules
+                {getIndex("int"), 4},
+                {getIndex("uint"), 5},
+                {getIndex("dword"), 6},
+                {getIndex("int32_t"), 7},
+                {getIndex("uint32_t"), 8},
+                {getIndex("int64_t"), 9},
+                {getIndex("uint64_t"), 10},
+                {getIndex("half"), 11 << 5},  // floats win all conversions, even halfs
+                {getIndex("float"), 12 << 5},
+                {getIndex("double"), 13 << 5},
+            };
+            // `basesize` getter, but 1 for bool: (physical size of extern bool is considered 32bits in HLSL)
+            auto getRankSizeof = [&](int scalarId)
+            {
+                assert(string_view{"bool"} == Predefined::Scalar[0]);  // verify that 0 is the hard index of bool.
+                bool isBool = scalarId == 0;
+                return isBool ? 1 : m_baseSize;
+            };
+            // The shift method is taken from clang, I suppose it's a multi-parameter order cramed into bits.
+            // so because 10 is the largest subrank, shift by 4 should separate sizeof space and subank space.
+            m_conversionRank = (getRankSizeof(m_underlyingScalar) << 4) + subranks.at(m_underlyingScalar);
         }
 
         /// Get the size of the whole type considering dimensions

+ 1 - 1
src/PadToAttributeMutator.cpp

@@ -354,7 +354,7 @@ namespace AZ::ShaderCompiler
             else if (varInfo.GetTypeClass() == TypeClass::Enum)
             {
                 auto* asClassInfo = m_ir.GetSymbolSubAs<ClassInfo>(varInfo.GetTypeId().GetName());
-                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.GetBaseSize();
+                size = asClassInfo->Get<EnumerationInfo>()->m_underlyingType.m_arithmeticInfo.m_baseSize;
             }
 
             offset = Packing::PackNextChunk(layoutPacking, size, startAt);