HLSL: Add bounds checking, shared with GLSL. Partially address #1032.
diff --git a/Test/baseResults/hlsl.constantbuffer.frag.out b/Test/baseResults/hlsl.constantbuffer.frag.out
index 2c7dafe..33c6727 100644
--- a/Test/baseResults/hlsl.constantbuffer.frag.out
+++ b/Test/baseResults/hlsl.constantbuffer.frag.out
@@ -45,7 +45,7 @@
0:24 direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
0:24 'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
0:24 Constant:
-0:24 2 (const int)
+0:24 1 (const int)
0:24 Constant:
0:24 3 (const int)
0:24 Constant:
@@ -113,7 +113,7 @@
0:24 direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
0:24 'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
0:24 Constant:
-0:24 2 (const int)
+0:24 1 (const int)
0:24 Constant:
0:24 3 (const int)
0:24 Constant:
@@ -231,7 +231,7 @@
54: 7(fvec4) FAdd 45 53
ReturnValue 54
56: Label
- 58: 41(ptr) AccessChain 18(cb3) 21 57 20
+ 58: 41(ptr) AccessChain 18(cb3) 20 57 20
59: 6(float) Load 58
60: 7(fvec4) CompositeConstruct 59 59 59 59
ReturnValue 60
diff --git a/Test/hlsl.constantbuffer.frag b/Test/hlsl.constantbuffer.frag
index d7a6ef5..c2b3a00 100644
--- a/Test/hlsl.constantbuffer.frag
+++ b/Test/hlsl.constantbuffer.frag
@@ -21,6 +21,6 @@
if (cb3[1][2].x)
return cb1.x + cb2[1].y + c1;
else
- return cb3[2][3].y;
+ return cb3[1][3].y;
}
diff --git a/glslang/MachineIndependent/ParseContextBase.cpp b/glslang/MachineIndependent/ParseContextBase.cpp
index 44fc0b4..447c038 100644
--- a/glslang/MachineIndependent/ParseContextBase.cpp
+++ b/glslang/MachineIndependent/ParseContextBase.cpp
@@ -234,6 +234,31 @@
linkageSymbols.push_back(&symbol);
}
+// Ensure index is in bounds, correct if necessary.
+// Give an error if not.
+void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
+{
+ if (index < 0) {
+ error(loc, "", "[", "index out of range '%d'", index);
+ index = 0;
+ } else if (type.isArray()) {
+ if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
+ error(loc, "", "[", "array index out of range '%d'", index);
+ index = type.getOuterArraySize() - 1;
+ }
+ } else if (type.isVector()) {
+ if (index >= type.getVectorSize()) {
+ error(loc, "", "[", "vector index out of range '%d'", index);
+ index = type.getVectorSize() - 1;
+ }
+ } else if (type.isMatrix()) {
+ if (index >= type.getMatrixCols()) {
+ error(loc, "", "[", "matrix index out of range '%d'", index);
+ index = type.getMatrixCols() - 1;
+ }
+ }
+}
+
// Make a shared symbol have a non-shared version that can be edited by the current
// compile, such that editing its type will not change the shared version and will
// effect all nodes already sharing it (non-shallow type),
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 42a2dc0..32cc4bf 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -429,29 +429,6 @@
return result;
}
-void TParseContext::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
-{
- if (index < 0) {
- error(loc, "", "[", "index out of range '%d'", index);
- index = 0;
- } else if (type.isArray()) {
- if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
- error(loc, "", "[", "array index out of range '%d'", index);
- index = type.getOuterArraySize() - 1;
- }
- } else if (type.isVector()) {
- if (index >= type.getVectorSize()) {
- error(loc, "", "[", "vector index out of range '%d'", index);
- index = type.getVectorSize() - 1;
- }
- } else if (type.isMatrix()) {
- if (index >= type.getMatrixCols()) {
- error(loc, "", "[", "matrix index out of range '%d'", index);
- index = type.getMatrixCols() - 1;
- }
- }
-}
-
// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
{
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 4bdd149..fb6d0bc 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -102,6 +102,8 @@
virtual void setLimits(const TBuiltInResource&) = 0;
+ void checkIndex(const TSourceLoc&, const TType&, int& index);
+
EShLanguage getLanguage() const { return language; }
void setScanContext(TScanContext* c) { scanContext = c; }
TScanContext* getScanContext() const { return scanContext; }
@@ -283,7 +285,6 @@
void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
- void checkIndex(const TSourceLoc&, const TType&, int& index);
void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
void makeEditable(TSymbol*&) override;
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index b49022b..1fbef6d 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -859,10 +859,8 @@
bool flattened = false;
int indexValue = 0;
- if (index->getQualifier().storage == EvqConst) {
+ if (index->getQualifier().isFrontEndConstant())
indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
- checkIndex(loc, base->getType(), indexValue);
- }
variableCheck(base);
if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
@@ -871,9 +869,11 @@
base->getAsSymbolNode()->getName().c_str(), "");
else
error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
- } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst)
+ } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) {
+ // both base and index are front-end constants
+ checkIndex(loc, base->getType(), indexValue);
return intermediate.foldDereference(base, indexValue, loc);
- else {
+ } else {
// at least one of base and index is variable...
if (base->getAsSymbolNode() && wasFlattened(base)) {
@@ -883,9 +883,11 @@
result = flattenAccess(base, indexValue);
flattened = (result != base);
} else {
- if (index->getQualifier().storage == EvqConst) {
+ if (index->getQualifier().isFrontEndConstant()) {
if (base->getType().isImplicitlySizedArray())
updateImplicitArraySize(loc, base, indexValue);
+ else
+ checkIndex(loc, base->getType(), indexValue);
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
} else {
result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
@@ -914,11 +916,6 @@
return result;
}
-void HlslParseContext::checkIndex(const TSourceLoc& /*loc*/, const TType& /*type*/, int& /*index*/)
-{
- // HLSL todo: any rules for index fixups?
-}
-
// Handle seeing a binary node with a math operation.
TIntermTyped* HlslParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op,
TIntermTyped* left, TIntermTyped* right)
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 19e4626..3c81067 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -73,7 +73,6 @@
TIntermTyped* handleVariable(const TSourceLoc&, const TString* string);
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
- void checkIndex(const TSourceLoc&, const TType&, int& index);
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);