Commit 185fb403 by Jamie Madill

Move function prototypes and declarations out of the .y

This will make the code easier to edit and maintain. BUG=none TEST=angle_unittests,angle_end2end_tests Change-Id: I955307d1209170fa99142103bc4d361c9eab1cc8 Reviewed-on: https://chromium-review.googlesource.com/286145Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent b61e173a
...@@ -1813,6 +1813,166 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) ...@@ -1813,6 +1813,166 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
} }
} }
void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
TFunction *function,
TIntermAggregate **aggregateOut)
{
const TSymbol *builtIn = symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
if (builtIn)
{
error(location, "built-in functions cannot be redefined", function->getName().c_str());
recover();
}
TFunction* prevDec = static_cast<TFunction*>(symbolTable.find(function->getMangledName(), getShaderVersion()));
//
// Note: 'prevDec' could be 'function' if this is the first time we've seen function
// as it would have just been put in the symbol table. Otherwise, we're looking up
// an earlier occurance.
//
if (prevDec->isDefined())
{
// Then this function already has a body.
error(location, "function already has a body", function->getName().c_str());
recover();
}
prevDec->setDefined();
//
// Overload the unique ID of the definition to be the same unique ID as the declaration.
// Eventually we will probably want to have only a single definition and just swap the
// arguments to be the definition's arguments.
//
function->setUniqueId(prevDec->getUniqueId());
// Raise error message if main function takes any parameters or return anything other than void
if (function->getName() == "main")
{
if (function->getParamCount() > 0)
{
error(location, "function cannot take any parameter(s)", function->getName().c_str());
recover();
}
if (function->getReturnType().getBasicType() != EbtVoid)
{
error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value");
recover();
}
}
//
// Remember the return type for later checking for RETURN statements.
//
setCurrentFunctionType(&(prevDec->getReturnType()));
setFunctionReturnsValue(false);
//
// Insert parameters into the symbol table.
// If the parameter has no name, it's not an error, just don't insert it
// (could be used for unused args).
//
// Also, accumulate the list of parameters into the HIL, so lower level code
// knows where to find parameters.
//
TIntermAggregate *paramNodes = new TIntermAggregate;
for (size_t i = 0; i < function->getParamCount(); i++)
{
const TConstParameter &param = function->getParam(i);
if (param.name != 0)
{
TVariable *variable = new TVariable(param.name, *param.type);
//
// Insert the parameters with name in the symbol table.
//
if (!symbolTable.declare(variable)) {
error(location, "redefinition", variable->getName().c_str());
recover();
delete variable;
}
//
// Add the parameter to the HIL
//
TIntermSymbol *symbol = intermediate.addSymbol(variable->getUniqueId(),
variable->getName(),
variable->getType(), location);
paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
}
else
{
paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
}
}
intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
*aggregateOut = paramNodes;
setLoopNestingLevel(0);
}
TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location,
TFunction *function)
{
//
// Multiple declarations of the same function are allowed.
//
// If this is a definition, the definition production code will check for redefinitions
// (we don't know at this point if it's a definition or not).
//
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
//
TFunction *prevDec = static_cast<TFunction*>(symbolTable.find(function->getMangledName(), getShaderVersion()));
if (prevDec)
{
if (prevDec->getReturnType() != function->getReturnType())
{
error(location,
"overloaded functions must have the same return type",
function->getReturnType().getBasicString());
recover();
}
for (size_t i = 0; i < prevDec->getParamCount(); ++i)
{
if (prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier())
{
error(location,
"overloaded functions must have the same parameter qualifiers",
function->getParam(i).type->getQualifierString());
recover();
}
}
}
//
// Check for previously declared variables using the same name.
//
TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
if (prevSym)
{
if (!prevSym->isFunction())
{
error(location, "redefinition", function->getName().c_str(), "function");
recover();
}
}
else
{
// Insert the unmangled name to detect potential future redefinition as a variable.
TFunction *newFunction = new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
symbolTable.getOuterLevel()->insertUnmangled(newFunction);
}
// We're at the inner scope level of the function's arguments and body statement.
// Add the function prototype to the surrounding scope instead.
symbolTable.getOuterLevel()->insert(function);
//
// If this is a redeclaration, it could also be a definition,
// in which case, we want to use the variable names from this one, and not the one that's
// being redeclared. So, pass back up this declaration, not the one in the symbol table.
//
return function;
}
TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
{ {
TPublicType publicType = publicTypeIn; TPublicType publicType = publicTypeIn;
......
...@@ -220,6 +220,11 @@ class TParseContext : angle::NonCopyable ...@@ -220,6 +220,11 @@ class TParseContext : angle::NonCopyable
TIntermTyped *initializer); TIntermTyped *initializer);
void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
void parseFunctionPrototype(const TSourceLoc &location,
TFunction *function,
TIntermAggregate **aggregateOut);
TFunction *parseFunctionDeclarator(const TSourceLoc &location,
TFunction *function);
TFunction *addConstructorFunc(const TPublicType &publicType); TFunction *addConstructorFunc(const TPublicType &publicType);
TIntermTyped *addConstructor(TIntermNode *arguments, TIntermTyped *addConstructor(TIntermNode *arguments,
TType *type, TType *type,
......
...@@ -664,57 +664,7 @@ declaration ...@@ -664,57 +664,7 @@ declaration
function_prototype function_prototype
: function_declarator RIGHT_PAREN { : function_declarator RIGHT_PAREN {
// $$.function = context->parseFunctionDeclarator(@2, $1);
// Multiple declarations of the same function are allowed.
//
// If this is a definition, the definition production code will check for redefinitions
// (we don't know at this point if it's a definition or not).
//
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
//
TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName(), context->getShaderVersion()));
if (prevDec) {
if (prevDec->getReturnType() != $1->getReturnType()) {
context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
context->recover();
}
for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
context->recover();
}
}
}
//
// Check for previously declared variables using the same name.
//
TSymbol *prevSym = context->symbolTable.find($1->getName(), context->getShaderVersion());
if (prevSym)
{
if (!prevSym->isFunction())
{
context->error(@2, "redefinition", $1->getName().c_str(), "function");
context->recover();
}
}
else
{
// Insert the unmangled name to detect potential future redefinition as a variable.
TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), &$1->getReturnType());
context->symbolTable.getOuterLevel()->insertUnmangled(function);
}
//
// If this is a redeclaration, it could also be a definition,
// in which case, we want to use the variable names from this one, and not the one that's
// being redeclared. So, pass back up this declaration, not the one in the symbol table.
//
$$.function = $1;
// We're at the inner scope level of the function's arguments and body statement.
// Add the function prototype to the surrounding scope instead.
context->symbolTable.getOuterLevel()->insert($$.function);
} }
; ;
...@@ -1665,95 +1615,7 @@ external_declaration ...@@ -1665,95 +1615,7 @@ external_declaration
function_definition function_definition
: function_prototype { : function_prototype {
TFunction* function = $1.function; context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate);
const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
if (builtIn)
{
context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
context->recover();
}
TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
//
// Note: 'prevDec' could be 'function' if this is the first time we've seen function
// as it would have just been put in the symbol table. Otherwise, we're looking up
// an earlier occurance.
//
if (prevDec->isDefined()) {
//
// Then this function already has a body.
//
context->error(@1, "function already has a body", function->getName().c_str());
context->recover();
}
prevDec->setDefined();
//
// Overload the unique ID of the definition to be the same unique ID as the declaration.
// Eventually we will probably want to have only a single definition and just swap the
// arguments to be the definition's arguments.
//
function->setUniqueId(prevDec->getUniqueId());
//
// Raise error message if main function takes any parameters or return anything other than void
//
if (function->getName() == "main") {
if (function->getParamCount() > 0) {
context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
context->recover();
}
if (function->getReturnType().getBasicType() != EbtVoid) {
context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
context->recover();
}
}
//
// Remember the return type for later checking for RETURN statements.
//
context->setCurrentFunctionType(&(prevDec->getReturnType()));
context->setFunctionReturnsValue(false);
//
// Insert parameters into the symbol table.
// If the parameter has no name, it's not an error, just don't insert it
// (could be used for unused args).
//
// Also, accumulate the list of parameters into the HIL, so lower level code
// knows where to find parameters.
//
TIntermAggregate* paramNodes = new TIntermAggregate;
for (size_t i = 0; i < function->getParamCount(); i++) {
const TConstParameter& param = function->getParam(i);
if (param.name != 0) {
TVariable *variable = new TVariable(param.name, *param.type);
//
// Insert the parameters with name in the symbol table.
//
if (! context->symbolTable.declare(variable)) {
context->error(@1, "redefinition", variable->getName().c_str());
context->recover();
delete variable;
}
//
// Add the parameter to the HIL
//
paramNodes = context->intermediate.growAggregate(
paramNodes,
context->intermediate.addSymbol(variable->getUniqueId(),
variable->getName(),
variable->getType(), @1),
@1);
} else {
paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
}
}
context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
$1.intermAggregate = paramNodes;
context->setLoopNestingLevel(0);
} }
compound_statement_no_new_scope { compound_statement_no_new_scope {
//?? Check that all paths return a value if return type != void ? //?? Check that all paths return a value if return type != void ?
......
...@@ -703,25 +703,25 @@ static const yytype_uint16 yyrline[] = ...@@ -703,25 +703,25 @@ static const yytype_uint16 yyrline[] =
488, 495, 496, 503, 504, 510, 511, 517, 518, 524, 488, 495, 496, 503, 504, 510, 511, 517, 518, 524,
525, 531, 532, 540, 541, 542, 543, 547, 548, 549, 525, 531, 532, 540, 541, 542, 543, 547, 548, 549,
553, 557, 561, 565, 572, 575, 586, 594, 602, 630, 553, 557, 561, 565, 572, 575, 586, 594, 602, 630,
636, 647, 651, 655, 659, 666, 722, 725, 732, 740, 636, 647, 651, 655, 659, 666, 672, 675, 682, 690,
761, 788, 798, 826, 831, 841, 846, 856, 859, 862, 711, 738, 748, 776, 781, 791, 796, 806, 809, 812,
865, 871, 878, 881, 885, 889, 894, 899, 906, 910, 815, 821, 828, 831, 835, 839, 844, 849, 856, 860,
914, 918, 923, 928, 932, 939, 949, 955, 958, 964, 864, 868, 873, 878, 882, 889, 899, 905, 908, 914,
970, 977, 986, 996, 1004, 1007, 1014, 1018, 1022, 1027, 920, 927, 936, 946, 954, 957, 964, 968, 972, 977,
1035, 1038, 1042, 1046, 1055, 1064, 1072, 1082, 1094, 1097, 985, 988, 992, 996, 1005, 1014, 1022, 1032, 1044, 1047,
1100, 1106, 1113, 1116, 1122, 1125, 1128, 1134, 1137, 1142, 1050, 1056, 1063, 1066, 1072, 1075, 1078, 1084, 1087, 1092,
1157, 1161, 1165, 1169, 1173, 1177, 1182, 1187, 1192, 1197, 1107, 1111, 1115, 1119, 1123, 1127, 1132, 1137, 1142, 1147,
1202, 1207, 1212, 1217, 1222, 1227, 1232, 1237, 1242, 1247, 1152, 1157, 1162, 1167, 1172, 1177, 1182, 1187, 1192, 1197,
1252, 1257, 1262, 1267, 1272, 1277, 1282, 1286, 1290, 1294, 1202, 1207, 1212, 1217, 1222, 1227, 1232, 1236, 1240, 1244,
1298, 1302, 1306, 1310, 1314, 1318, 1322, 1326, 1330, 1334, 1248, 1252, 1256, 1260, 1264, 1268, 1272, 1276, 1280, 1284,
1338, 1342, 1350, 1358, 1362, 1375, 1375, 1378, 1378, 1384, 1288, 1292, 1300, 1308, 1312, 1325, 1325, 1328, 1328, 1334,
1387, 1403, 1406, 1415, 1419, 1425, 1432, 1447, 1451, 1455, 1337, 1353, 1356, 1365, 1369, 1375, 1382, 1397, 1401, 1405,
1456, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1472, 1473, 1406, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1422, 1423,
1473, 1473, 1483, 1484, 1488, 1488, 1489, 1489, 1494, 1497, 1423, 1423, 1433, 1434, 1438, 1438, 1439, 1439, 1444, 1447,
1507, 1510, 1516, 1517, 1521, 1529, 1533, 1540, 1540, 1547, 1457, 1460, 1466, 1467, 1471, 1479, 1483, 1490, 1490, 1497,
1550, 1557, 1562, 1577, 1577, 1582, 1582, 1589, 1589, 1597, 1500, 1507, 1512, 1527, 1527, 1532, 1532, 1539, 1539, 1547,
1600, 1606, 1609, 1615, 1619, 1626, 1629, 1632, 1635, 1638, 1550, 1556, 1559, 1565, 1569, 1576, 1579, 1582, 1585, 1588,
1647, 1651, 1658, 1661, 1667, 1667 1597, 1601, 1608, 1611, 1617, 1617
}; };
#endif #endif
...@@ -3163,57 +3163,7 @@ yyreduce: ...@@ -3163,57 +3163,7 @@ yyreduce:
case 95: case 95:
{ {
// (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function));
// Multiple declarations of the same function are allowed.
//
// If this is a definition, the definition production code will check for redefinitions
// (we don't know at this point if it's a definition or not).
//
// Redeclarations are allowed. But, return types and parameter qualifiers must match.
//
TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[-1].interm.function)->getMangledName(), context->getShaderVersion()));
if (prevDec) {
if (prevDec->getReturnType() != (yyvsp[-1].interm.function)->getReturnType()) {
context->error((yylsp[0]), "overloaded functions must have the same return type", (yyvsp[-1].interm.function)->getReturnType().getBasicString());
context->recover();
}
for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
if (prevDec->getParam(i).type->getQualifier() != (yyvsp[-1].interm.function)->getParam(i).type->getQualifier()) {
context->error((yylsp[0]), "overloaded functions must have the same parameter qualifiers", (yyvsp[-1].interm.function)->getParam(i).type->getQualifierString());
context->recover();
}
}
}
//
// Check for previously declared variables using the same name.
//
TSymbol *prevSym = context->symbolTable.find((yyvsp[-1].interm.function)->getName(), context->getShaderVersion());
if (prevSym)
{
if (!prevSym->isFunction())
{
context->error((yylsp[0]), "redefinition", (yyvsp[-1].interm.function)->getName().c_str(), "function");
context->recover();
}
}
else
{
// Insert the unmangled name to detect potential future redefinition as a variable.
TFunction *function = new TFunction(NewPoolTString((yyvsp[-1].interm.function)->getName().c_str()), &(yyvsp[-1].interm.function)->getReturnType());
context->symbolTable.getOuterLevel()->insertUnmangled(function);
}
//
// If this is a redeclaration, it could also be a definition,
// in which case, we want to use the variable names from this one, and not the one that's
// being redeclared. So, pass back up this declaration, not the one in the symbol table.
//
(yyval.interm).function = (yyvsp[-1].interm.function);
// We're at the inner scope level of the function's arguments and body statement.
// Add the function prototype to the surrounding scope instead.
context->symbolTable.getOuterLevel()->insert((yyval.interm).function);
} }
break; break;
...@@ -4903,95 +4853,7 @@ yyreduce: ...@@ -4903,95 +4853,7 @@ yyreduce:
case 274: case 274:
{ {
TFunction* function = (yyvsp[0].interm).function; context->parseFunctionPrototype((yylsp[0]), (yyvsp[0].interm).function, &(yyvsp[0].interm).intermAggregate);
const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->getShaderVersion());
if (builtIn)
{
context->error((yylsp[0]), "built-in functions cannot be redefined", function->getName().c_str());
context->recover();
}
TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->getShaderVersion()));
//
// Note: 'prevDec' could be 'function' if this is the first time we've seen function
// as it would have just been put in the symbol table. Otherwise, we're looking up
// an earlier occurance.
//
if (prevDec->isDefined()) {
//
// Then this function already has a body.
//
context->error((yylsp[0]), "function already has a body", function->getName().c_str());
context->recover();
}
prevDec->setDefined();
//
// Overload the unique ID of the definition to be the same unique ID as the declaration.
// Eventually we will probably want to have only a single definition and just swap the
// arguments to be the definition's arguments.
//
function->setUniqueId(prevDec->getUniqueId());
//
// Raise error message if main function takes any parameters or return anything other than void
//
if (function->getName() == "main") {
if (function->getParamCount() > 0) {
context->error((yylsp[0]), "function cannot take any parameter(s)", function->getName().c_str());
context->recover();
}
if (function->getReturnType().getBasicType() != EbtVoid) {
context->error((yylsp[0]), "", function->getReturnType().getBasicString(), "main function cannot return a value");
context->recover();
}
}
//
// Remember the return type for later checking for RETURN statements.
//
context->setCurrentFunctionType(&(prevDec->getReturnType()));
context->setFunctionReturnsValue(false);
//
// Insert parameters into the symbol table.
// If the parameter has no name, it's not an error, just don't insert it
// (could be used for unused args).
//
// Also, accumulate the list of parameters into the HIL, so lower level code
// knows where to find parameters.
//
TIntermAggregate* paramNodes = new TIntermAggregate;
for (size_t i = 0; i < function->getParamCount(); i++) {
const TConstParameter& param = function->getParam(i);
if (param.name != 0) {
TVariable *variable = new TVariable(param.name, *param.type);
//
// Insert the parameters with name in the symbol table.
//
if (! context->symbolTable.declare(variable)) {
context->error((yylsp[0]), "redefinition", variable->getName().c_str());
context->recover();
delete variable;
}
//
// Add the parameter to the HIL
//
paramNodes = context->intermediate.growAggregate(
paramNodes,
context->intermediate.addSymbol(variable->getUniqueId(),
variable->getName(),
variable->getType(), (yylsp[0])),
(yylsp[0]));
} else {
paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yylsp[0])), (yylsp[0]));
}
}
context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[0]));
(yyvsp[0].interm).intermAggregate = paramNodes;
context->setLoopNestingLevel(0);
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment