HLSL: Add typedef grammar and production.
diff --git a/Test/baseResults/hlsl.typedef.frag.out b/Test/baseResults/hlsl.typedef.frag.out
new file mode 100755
index 0000000..ca0235a
--- /dev/null
+++ b/Test/baseResults/hlsl.typedef.frag.out
@@ -0,0 +1,132 @@
+hlsl.typedef.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:12 Function Definition: ShaderFunction(vf4;i1; (global 4-component vector of float)
+0:4 Function Parameters:
+0:4 'input' (in 4-component vector of float)
+0:4 'ii' (in int)
+0:? Sequence
+0:6 Sequence
+0:6 move second child to first child (temp 4-component vector of float)
+0:6 'a1' (temp 4-component vector of float)
+0:6 Constant:
+0:6 1.000000
+0:6 1.000000
+0:6 1.000000
+0:6 1.000000
+0:7 Sequence
+0:7 move second child to first child (temp int)
+0:7 'i' (temp int)
+0:7 Constant:
+0:7 2 (const int)
+0:9 Sequence
+0:9 move second child to first child (temp int)
+0:9 'j' (temp int)
+0:9 'ii' (in int)
+0:10 Branch: Return with expression
+0:10 add (temp 4-component vector of float)
+0:10 component-wise multiply (temp 4-component vector of float)
+0:10 'input' (in 4-component vector of float)
+0:10 'a1' (temp 4-component vector of float)
+0:10 Construct vec4 (global 4-component vector of float)
+0:10 Convert int to float (temp float)
+0:10 add (temp int)
+0:10 'i' (temp int)
+0:10 'j' (temp int)
+0:? Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:12 Function Definition: ShaderFunction(vf4;i1; (global 4-component vector of float)
+0:4 Function Parameters:
+0:4 'input' (in 4-component vector of float)
+0:4 'ii' (in int)
+0:? Sequence
+0:6 Sequence
+0:6 move second child to first child (temp 4-component vector of float)
+0:6 'a1' (temp 4-component vector of float)
+0:6 Constant:
+0:6 1.000000
+0:6 1.000000
+0:6 1.000000
+0:6 1.000000
+0:7 Sequence
+0:7 move second child to first child (temp int)
+0:7 'i' (temp int)
+0:7 Constant:
+0:7 2 (const int)
+0:9 Sequence
+0:9 move second child to first child (temp int)
+0:9 'j' (temp int)
+0:9 'ii' (in int)
+0:10 Branch: Return with expression
+0:10 add (temp 4-component vector of float)
+0:10 component-wise multiply (temp 4-component vector of float)
+0:10 'input' (in 4-component vector of float)
+0:10 'a1' (temp 4-component vector of float)
+0:10 Construct vec4 (global 4-component vector of float)
+0:10 Convert int to float (temp float)
+0:10 add (temp int)
+0:10 'i' (temp int)
+0:10 'j' (temp int)
+0:? Linker Objects
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 34
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "PixelShaderFunction"
+ ExecutionMode 4 OriginUpperLeft
+ Source HLSL 450
+ Name 4 "PixelShaderFunction"
+ Name 14 "ShaderFunction(vf4;i1;"
+ Name 12 "input"
+ Name 13 "ii"
+ Name 16 "a1"
+ Name 19 "i"
+ Name 21 "j"
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 9: TypeInt 32 1
+ 10: TypePointer Function 9(int)
+ 11: TypeFunction 7(fvec4) 8(ptr) 10(ptr)
+ 17: 6(float) Constant 1065353216
+ 18: 7(fvec4) ConstantComposite 17 17 17 17
+ 20: 9(int) Constant 2
+4(PixelShaderFunction): 2 Function None 3
+ 5: Label
+ FunctionEnd
+14(ShaderFunction(vf4;i1;): 7(fvec4) Function None 11
+ 12(input): 8(ptr) FunctionParameter
+ 13(ii): 10(ptr) FunctionParameter
+ 15: Label
+ 16(a1): 8(ptr) Variable Function
+ 19(i): 10(ptr) Variable Function
+ 21(j): 10(ptr) Variable Function
+ Store 16(a1) 18
+ Store 19(i) 20
+ 22: 9(int) Load 13(ii)
+ Store 21(j) 22
+ 23: 7(fvec4) Load 12(input)
+ 24: 7(fvec4) Load 16(a1)
+ 25: 7(fvec4) FMul 23 24
+ 26: 9(int) Load 19(i)
+ 27: 9(int) Load 21(j)
+ 28: 9(int) IAdd 26 27
+ 29: 6(float) ConvertSToF 28
+ 30: 7(fvec4) CompositeConstruct 29 29 29 29
+ 31: 7(fvec4) FAdd 25 30
+ ReturnValue 31
+ FunctionEnd
diff --git a/Test/hlsl.typedef.frag b/Test/hlsl.typedef.frag
new file mode 100644
index 0000000..b09785e
--- /dev/null
+++ b/Test/hlsl.typedef.frag
@@ -0,0 +1,11 @@
+typedef float4 myVec4;
+
+float4 ShaderFunction(float4 input, int ii) : COLOR0
+{
+ typedef int myInt;
+ myVec4 a1 = myVec4(1.0);
+ myInt i = 2;
+ typedef myInt myInt2;
+ myInt2 j = ii;
+ return input * a1 + myVec4(i + j);
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 040739f..a004419 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -104,6 +104,7 @@
{"hlsl.switch.frag", "PixelShaderFunction"},
{"hlsl.swizzle.frag", "PixelShaderFunction"},
{"hlsl.templatetypes.frag", "PixelShaderFunction"},
+ {"hlsl.typedef.frag", "PixelShaderFunction"},
{"hlsl.whileLoop.frag", "PixelShaderFunction"},
{"hlsl.void.frag", "PixelShaderFunction"},
}),
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index d92debd..ee8ebf3 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -108,6 +108,7 @@
// declaration
// : fully_specified_type declarator_list SEMICOLON
// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
+// | typedef declaration
//
// declarator_list
// : declarator COMMA declarator COMMA declarator... // zero or more declarators
@@ -130,6 +131,9 @@
node = nullptr;
bool list = false;
+ // typedef
+ bool typedefDecl = acceptTokenClass(EHTokTypedef);
+
// fully_specified_type
TType type;
if (! acceptFullySpecifiedType(type))
@@ -150,9 +154,14 @@
if (peekTokenClass(EHTokLeftBrace)) {
if (list)
parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
+ if (typedefDecl)
+ parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
return acceptFunctionDefinition(*function, node);
- } else
+ } else {
+ if (typedefDecl)
+ parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
parseContext.handleFunctionDeclarator(idToken.loc, *function, true);
+ }
} else {
// a variable declaration
@@ -166,19 +175,25 @@
// EQUAL assignment_expression
TIntermTyped* expressionNode = nullptr;
if (acceptTokenClass(EHTokAssign)) {
+ if (typedefDecl)
+ parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
if (! acceptAssignmentExpression(expressionNode)) {
expected("initializer");
return false;
}
}
- // Declare the variable and add any initializer code to the AST.
- // The top-level node is always made into an aggregate, as that's
- // historically how the AST has been.
- node = intermediate.growAggregate(node,
- parseContext.declareVariable(idToken.loc, *idToken.string, type,
- arraySizes, expressionNode),
- idToken.loc);
+ if (typedefDecl)
+ parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
+ else {
+ // Declare the variable and add any initializer code to the AST.
+ // The top-level node is always made into an aggregate, as that's
+ // historically how the AST has been.
+ node = intermediate.growAggregate(node,
+ parseContext.declareVariable(idToken.loc, *idToken.string, type,
+ arraySizes, expressionNode),
+ idToken.loc);
+ }
}
if (acceptTokenClass(EHTokComma)) {
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 22cd1f4..43f685c 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -3019,6 +3019,27 @@
}
//
+// Do everything necessary to handle a typedef declaration, for a single symbol.
+//
+// 'parseType' is the type part of the declaration (to the left)
+// 'arraySizes' is the arrayness tagged on the identifier (to the right)
+//
+void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes)
+{
+ TType type;
+ type.deepCopy(parseType);
+
+ // Arrayness is potentially coming both from the type and from the
+ // variable: "int[] a[];" or just one or the other.
+ // Merge it all to the type, so all arrayness is part of the type.
+ arrayDimMerge(type, arraySizes);
+
+ TVariable* typeSymbol = new TVariable(&identifier, type, true);
+ if (! symbolTable.insert(*typeSymbol))
+ error(loc, "name already defined", "typedef", identifier.c_str());
+}
+
+//
// Do everything necessary to handle a variable (non-block) declaration.
// Either redeclaring a variable, or making a new one, updating the symbol
// table, and all error checking.
@@ -3026,7 +3047,7 @@
// Returns a subtree node that computes an initializer, if needed.
// Returns nullptr if there is no code to execute for initialization.
//
-// 'publicType' is the type part of the declaration (to the left)
+// 'parseType' is the type part of the declaration (to the left)
// 'arraySizes' is the arrayness tagged on the identifier (to the right)
//
TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes, TIntermTyped* initializer)
@@ -3036,7 +3057,7 @@
if (type.isImplicitlySizedArray()) {
// Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
// of different sizes, for this case sharing the shallow copy of arrayness
- // with the publicType oversubscribes it, so get a deep copy of the arrayness.
+ // with the parseType oversubscribes it, so get a deep copy of the arrayness.
type.newArraySizes(*parseType.getArraySizes());
}
@@ -3045,7 +3066,7 @@
// Check for redeclaration of built-ins and/or attempting to declare a reserved name
bool newDeclaration = false; // true if a new entry gets added to the symbol table
- TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers, newDeclaration);
+ TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), parseType.shaderQualifiers, newDeclaration);
inheritGlobalDefaults(type.getQualifier());
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 5023371..9b3254d 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -126,6 +126,7 @@
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0);
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);