Browse Source

[spirv] Support handling of aliases in v2.

With this change, all legaliztion tests pass.
Ehsan Nasiri 6 years ago
parent
commit
cf6b802bd0

+ 1 - 1
tools/clang/include/clang/SPIRV/LowerTypeVisitor.h

@@ -84,7 +84,7 @@ private:
   /// Returns false if type is a SPIR-V col-major matrix or array of matrices.
   /// Returns false if type is a SPIR-V col-major matrix or array of matrices.
   /// It does so by checking the majorness of the HLSL matrix either with
   /// It does so by checking the majorness of the HLSL matrix either with
   /// explicit attribute or implicit command-line option.
   /// explicit attribute or implicit command-line option.
-  /// 
+  ///
   /// Note that HLSL matrices are conceptually row major, while SPIR-V matrices
   /// Note that HLSL matrices are conceptually row major, while SPIR-V matrices
   /// are conceptually column major. We are mapping what HLSL semantically mean
   /// are conceptually column major. We are mapping what HLSL semantically mean
   /// a row into a column here.
   /// a row into a column here.

+ 2 - 2
tools/clang/lib/SPIRV/LowerTypeVisitor.cpp

@@ -328,11 +328,11 @@ const SpirvType *LowerTypeVisitor::lowerType(QualType type,
         // Literal types.
         // Literal types.
         case BuiltinType::LitInt:
         case BuiltinType::LitInt:
           // TODO: analyze adjacent instructions for type hints
           // TODO: analyze adjacent instructions for type hints
-          //emitError("TODO: literal int", srcLoc);
+          // emitError("TODO: literal int", srcLoc);
           return spvContext.getUIntType(64);
           return spvContext.getUIntType(64);
         case BuiltinType::LitFloat: {
         case BuiltinType::LitFloat: {
           // TODO: analyze adjacent instructions for type hints
           // TODO: analyze adjacent instructions for type hints
-          //emitError("TODO: literal float", srcLoc);
+          // emitError("TODO: literal float", srcLoc);
           return spvContext.getFloatType(64);
           return spvContext.getFloatType(64);
 
 
         default:
         default:

+ 3 - 26
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -878,7 +878,6 @@ SpirvInstruction *SPIRVEmitter::loadIfGLValue(const Expr *expr,
   //
   //
   // Note: legalization specific code
   // Note: legalization specific code
   if (isReferencingNonAliasStructuredOrByteBuffer(expr)) {
   if (isReferencingNonAliasStructuredOrByteBuffer(expr)) {
-    info->setRValue();
     return info;
     return info;
   }
   }
 
 
@@ -962,30 +961,12 @@ bool SPIRVEmitter::loadIfAliasVarRef(const Expr *varExpr,
   assert(instr);
   assert(instr);
   if ((*instr) && (*instr)->containsAliasComponent() &&
   if ((*instr) && (*instr)->containsAliasComponent() &&
       isAKindOfStructuredOrByteBuffer(varExpr->getType())) {
       isAKindOfStructuredOrByteBuffer(varExpr->getType())) {
-    // Aliased-to variables are all in the Uniform storage class with GLSL
-    // std430 layout rules.
-
     // Load the pointer of the aliased-to-variable if the expression has a
     // Load the pointer of the aliased-to-variable if the expression has a
-    // pointer to pointer type. That is, the expression itself is a lvalue.
-    // (Note that we translate alias function return values as pointer types,
-    // not pointer to pointer types.)
-
+    // pointer to pointer type.
     if (varExpr->isGLValue())
     if (varExpr->isGLValue())
-      *instr = spvBuilder.createLoad(
-          spvContext.getPointerType(varExpr->getType(),
-                                    spv::StorageClass::Uniform),
-          *instr);
-
-    (*instr)->setStorageClass(spv::StorageClass::Uniform);
-    (*instr)->setLayoutRule(spirvOptions.sBufferLayoutRule);
-    // Now it is a pointer to the global resource, which is lvalue.
-    (*instr)->setRValue(false);
-    // Set to false to indicate that we've performed dereference over the
-    // pointer-to-pointer and now should fallback to the normal path
-    (*instr)->setContainsAliasComponent(false);
+      *instr = spvBuilder.createLoad(varExpr->getType(), *instr);
     return true;
     return true;
   }
   }
-
   return false;
   return false;
 }
 }
 
 
@@ -2135,11 +2116,6 @@ SpirvInstruction *SPIRVEmitter::processCall(const CallExpr *callExpr) {
     }
     }
   }
   }
 
 
-  // Inherit the SpirvEvalInfo from the function definition
-  // TODO (ehsan): Verify this is OK.
-  // return declIdMapper.getDeclEvalInfo(callee).setResultId(retVal);
-  retVal->setContainsAliasComponent(func->constainsAliasComponent());
-  retVal->setRValue(func->isRValue());
   return retVal;
   return retVal;
 }
 }
 
 
@@ -6115,6 +6091,7 @@ SpirvInstruction *SPIRVEmitter::turnIntoElementPtr(
     const auto var = createTemporaryVar(baseType, varName, base);
     const auto var = createTemporaryVar(baseType, varName, base);
     var->setLayoutRule(SpirvLayoutRule::Void);
     var->setLayoutRule(SpirvLayoutRule::Void);
     var->setStorageClass(spv::StorageClass::Function);
     var->setStorageClass(spv::StorageClass::Function);
+    var->setContainsAliasComponent(base->containsAliasComponent());
     accessChainBase = var;
     accessChainBase = var;
   }
   }
 
 

+ 43 - 3
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -11,6 +11,7 @@
 #include "CapabilityVisitor.h"
 #include "CapabilityVisitor.h"
 #include "LiteralTypeVisitor.h"
 #include "LiteralTypeVisitor.h"
 #include "TypeTranslator.h"
 #include "TypeTranslator.h"
+#include "clang/SPIRV/AstTypeProbe.h"
 #include "clang/SPIRV/EmitVisitor.h"
 #include "clang/SPIRV/EmitVisitor.h"
 #include "clang/SPIRV/LowerTypeVisitor.h"
 #include "clang/SPIRV/LowerTypeVisitor.h"
 
 
@@ -184,9 +185,20 @@ SpirvLoad *SpirvBuilder::createLoad(QualType resultType,
   auto *instruction =
   auto *instruction =
       new (context) SpirvLoad(resultType, /*id*/ 0, loc, pointer);
       new (context) SpirvLoad(resultType, /*id*/ 0, loc, pointer);
   instruction->setStorageClass(pointer->getStorageClass());
   instruction->setStorageClass(pointer->getStorageClass());
-  instruction->setRValue();
   instruction->setLayoutRule(pointer->getLayoutRule());
   instruction->setLayoutRule(pointer->getLayoutRule());
   instruction->setNonUniform(pointer->isNonUniform());
   instruction->setNonUniform(pointer->isNonUniform());
+  instruction->setRValue(true);
+
+  if (pointer->containsAliasComponent() &&
+      isAKindOfStructuredOrByteBuffer(resultType)) {
+    instruction->setStorageClass(spv::StorageClass::Uniform);
+    // Now it is a pointer to the global resource, which is lvalue.
+    instruction->setRValue(false);
+    // Set to false to indicate that we've performed dereference over the
+    // pointer-to-pointer and now should fallback to the normal path
+    instruction->setContainsAliasComponent(false);
+  }
+
   insertPoint->addInstruction(instruction);
   insertPoint->addInstruction(instruction);
   return instruction;
   return instruction;
 }
 }
@@ -199,9 +211,9 @@ SpirvLoad *SpirvBuilder::createLoad(const SpirvType *resultType,
       new (context) SpirvLoad(/*QualType*/ {}, /*id*/ 0, loc, pointer);
       new (context) SpirvLoad(/*QualType*/ {}, /*id*/ 0, loc, pointer);
   instruction->setResultType(resultType);
   instruction->setResultType(resultType);
   instruction->setStorageClass(pointer->getStorageClass());
   instruction->setStorageClass(pointer->getStorageClass());
-  instruction->setRValue();
   instruction->setLayoutRule(pointer->getLayoutRule());
   instruction->setLayoutRule(pointer->getLayoutRule());
   instruction->setNonUniform(pointer->isNonUniform());
   instruction->setNonUniform(pointer->isNonUniform());
+  instruction->setRValue(true);
   insertPoint->addInstruction(instruction);
   insertPoint->addInstruction(instruction);
   return instruction;
   return instruction;
 }
 }
@@ -220,7 +232,19 @@ SpirvBuilder::createFunctionCall(QualType returnType, SpirvFunction *func,
   assert(insertPoint && "null insert point");
   assert(insertPoint && "null insert point");
   auto *instruction =
   auto *instruction =
       new (context) SpirvFunctionCall(returnType, /*id*/ 0, loc, func, params);
       new (context) SpirvFunctionCall(returnType, /*id*/ 0, loc, func, params);
-  instruction->setRValue();
+  instruction->setRValue(func->isRValue());
+  instruction->setContainsAliasComponent(func->constainsAliasComponent());
+
+  if (func->constainsAliasComponent() &&
+      isAKindOfStructuredOrByteBuffer(returnType)) {
+    instruction->setStorageClass(spv::StorageClass::Uniform);
+    // Now it is a pointer to the global resource, which is lvalue.
+    instruction->setRValue(false);
+    // Set to false to indicate that we've performed dereference over the
+    // pointer-to-pointer and now should fallback to the normal path
+    instruction->setContainsAliasComponent(false);
+  }
+
   insertPoint->addInstruction(instruction);
   insertPoint->addInstruction(instruction);
   return instruction;
   return instruction;
 }
 }
@@ -238,6 +262,14 @@ SpirvBuilder::createAccessChain(QualType resultType, SpirvInstruction *base,
   for (auto *index : indexes)
   for (auto *index : indexes)
     isNonUniform = isNonUniform || index->isNonUniform();
     isNonUniform = isNonUniform || index->isNonUniform();
   instruction->setNonUniform(isNonUniform);
   instruction->setNonUniform(isNonUniform);
+  instruction->setContainsAliasComponent(base->containsAliasComponent());
+
+  // If doing an access chain into a structured or byte address buffer, make
+  // sure the layout rule is sBufferLayoutRule.
+  if (base->hasAstResultType() &&
+      isAKindOfStructuredOrByteBuffer(base->getAstResultType()))
+    instruction->setLayoutRule(spirvOptions.sBufferLayoutRule);
+
   insertPoint->addInstruction(instruction);
   insertPoint->addInstruction(instruction);
   return instruction;
   return instruction;
 }
 }
@@ -255,6 +287,14 @@ SpirvAccessChain *SpirvBuilder::createAccessChain(
   for (auto *index : indexes)
   for (auto *index : indexes)
     isNonUniform = isNonUniform || index->isNonUniform();
     isNonUniform = isNonUniform || index->isNonUniform();
   instruction->setNonUniform(isNonUniform);
   instruction->setNonUniform(isNonUniform);
+  instruction->setContainsAliasComponent(base->containsAliasComponent());
+
+  // If doing an access chain into a structured or byte address buffer, make
+  // sure the layout rule is sBufferLayoutRule.
+  if (base->hasAstResultType() &&
+      isAKindOfStructuredOrByteBuffer(base->getAstResultType()))
+    instruction->setLayoutRule(spirvOptions.sBufferLayoutRule);
+
   insertPoint->addInstruction(instruction);
   insertPoint->addInstruction(instruction);
   return instruction;
   return instruction;
 }
 }