Commit c4ba3bef by Olli Etuaho

Refactor addFunctionCallOrMethod out of glslang.y

TEST=angle_unittests BUG=angle:911 Change-Id: I6d4c0f0bfbf9e6252e241ae5bb1b6acdb463fce6 Reviewed-on: https://chromium-review.googlesource.com/255451Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5dbece59
...@@ -2793,6 +2793,136 @@ TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, ...@@ -2793,6 +2793,136 @@ TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue,
return intermediate.addBranch(op, returnValue, loc); return intermediate.addBranch(op, returnValue, loc);
} }
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
const TSourceLoc &loc, bool *fatalError)
{
*fatalError = false;
TOperator op = fnCall->getBuiltInOp();
TIntermTyped *callNode = nullptr;
if (op != EOpNull)
{
//
// Then this should be a constructor.
// Don't go through the symbol table for constructors.
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (!constructorErrorCheck(loc, node, *fnCall, op, &type))
{
//
// It's a constructor, of type 'type'.
//
callNode = addConstructor(node, &type, op, fnCall, loc);
}
else
{
recover();
callNode = intermediate.setAggregateOperator(nullptr, op, loc);
}
callNode->setType(type);
}
else
{
//
// Not a constructor. Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
fnCandidate = findFunction(loc, fnCall, shaderVersion, &builtIn);
if (fnCandidate)
{
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
extensionErrorCheck(loc, fnCandidate->getExtension()))
{
recover();
}
op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull)
{
//
// A function call mapped to a built-in operation.
//
if (fnCandidate->getParamCount() == 1)
{
//
// Treat it like a built-in unary operator.
//
callNode = intermediate.addUnaryMath(op, node, loc);
if (callNode == nullptr)
{
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: "
<< static_cast<TIntermTyped*>(node)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
error(node->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
*fatalError = true;
return nullptr;
}
const TType& returnType = fnCandidate->getReturnType();
if (returnType.getBasicType() == EbtBool)
{
// Bool types should not have precision, so we'll override any precision
// that might have been set by addUnaryMath.
callNode->setType(returnType);
}
else
{
// addUnaryMath has set the precision of the node based on the operand.
callNode->setTypePreservePrecision(returnType);
}
}
else
{
TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, op, loc);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
callNode = aggregate;
// Some built-in functions have out parameters too.
functionCallLValueErrorCheck(fnCandidate, aggregate);
}
}
else
{
// This is a real function call
TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, EOpFunctionCall, loc);
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
callNode = aggregate;
functionCallLValueErrorCheck(fnCandidate, aggregate);
}
}
else
{
// error message was put out by findFunction()
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), loc);
recover();
}
}
delete fnCall;
return callNode;
}
// //
// Parse an array of strings using yyparse. // Parse an array of strings using yyparse.
......
...@@ -179,6 +179,9 @@ struct TParseContext { ...@@ -179,6 +179,9 @@ struct TParseContext {
TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
const TSourceLoc &loc, bool *fatalError);
}; };
int PaParseStrings(size_t count, const char* const string[], const int length[], int PaParseStrings(size_t count, const char* const string[], const int length[],
......
...@@ -293,112 +293,12 @@ integer_expression ...@@ -293,112 +293,12 @@ integer_expression
function_call function_call
: function_call_or_method { : function_call_or_method {
TFunction* fnCall = $1.function; bool fatalError = false;
TOperator op = fnCall->getBuiltInOp(); $$ = context->addFunctionCallOrMethod($1.function, $1.intermNode, @1, &fatalError);
if (fatalError)
if (op != EOpNull)
{ {
//
// Then this should be a constructor.
// Don't go through the symbol table for constructors.
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
$$ = 0;
} else {
//
// It's a constructor, of type 'type'.
//
$$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
}
if ($$ == 0) {
context->recover();
$$ = context->intermediate.setAggregateOperator(0, op, @1);
}
$$->setType(type);
} else {
//
// Not a constructor. Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn);
if (fnCandidate) {
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
context->recover();
}
op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) {
//
// A function call mapped to a built-in operation.
//
if (fnCandidate->getParamCount() == 1) {
//
// Treat it like a built-in unary operator.
//
$$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
if ($$ == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
YYERROR; YYERROR;
} }
const TType& returnType = fnCandidate->getReturnType();
if (returnType.getBasicType() == EbtBool) {
// Bool types should not have precision, so we'll override any precision
// that might have been set by addUnaryMath.
$$->setType(returnType);
} else {
// addUnaryMath has set the precision of the node based on the operand.
$$->setTypePreservePrecision(returnType);
}
} else {
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
$$ = aggregate;
// Some built-in functions have out parameters too.
context->functionCallLValueErrorCheck(fnCandidate, aggregate);
}
} else {
// This is a real function call
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
$$ = aggregate;
context->functionCallLValueErrorCheck(fnCandidate, aggregate);
}
} else {
// error message was put out by PaFindFunction()
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
$$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
context->recover();
}
}
delete fnCall;
} }
; ;
......
...@@ -690,32 +690,32 @@ static const yytype_uint8 yytranslate[] = ...@@ -690,32 +690,32 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 209, 209, 210, 213, 237, 240, 245, 250, 255, 0, 209, 209, 210, 213, 237, 240, 245, 250, 255,
260, 266, 269, 272, 275, 278, 281, 287, 295, 406, 260, 266, 269, 272, 275, 278, 281, 287, 295, 306,
409, 417, 420, 426, 430, 437, 443, 452, 460, 463, 309, 317, 320, 326, 330, 337, 343, 352, 360, 363,
473, 476, 479, 482, 492, 493, 494, 495, 503, 504, 373, 376, 379, 382, 392, 393, 394, 395, 403, 404,
507, 510, 517, 518, 521, 527, 528, 532, 539, 540, 407, 410, 417, 418, 421, 427, 428, 432, 439, 440,
543, 546, 549, 555, 556, 559, 565, 566, 573, 574, 443, 446, 449, 455, 456, 459, 465, 466, 473, 474,
581, 582, 589, 590, 596, 597, 603, 604, 610, 611, 481, 482, 489, 490, 496, 497, 503, 504, 510, 511,
628, 629, 642, 643, 644, 645, 649, 650, 651, 655, 528, 529, 542, 543, 544, 545, 549, 550, 551, 555,
659, 663, 667, 674, 677, 688, 696, 704, 731, 737, 559, 563, 567, 574, 577, 588, 596, 604, 631, 637,
748, 752, 756, 760, 767, 823, 826, 833, 841, 862, 648, 652, 656, 660, 667, 723, 726, 733, 741, 762,
883, 893, 921, 926, 936, 941, 951, 954, 957, 960, 783, 793, 821, 826, 836, 841, 851, 854, 857, 860,
966, 973, 976, 980, 984, 988, 995, 999, 1003, 1010, 866, 873, 876, 880, 884, 888, 895, 899, 903, 910,
1014, 1018, 1025, 1034, 1040, 1043, 1049, 1055, 1062, 1071, 914, 918, 925, 934, 940, 943, 949, 955, 962, 971,
1080, 1088, 1091, 1098, 1102, 1109, 1112, 1116, 1120, 1129, 980, 988, 991, 998, 1002, 1009, 1012, 1016, 1020, 1029,
1138, 1146, 1156, 1168, 1171, 1174, 1180, 1187, 1190, 1196, 1038, 1046, 1056, 1068, 1071, 1074, 1080, 1087, 1090, 1096,
1199, 1202, 1208, 1211, 1226, 1230, 1234, 1238, 1242, 1246, 1099, 1102, 1108, 1111, 1126, 1130, 1134, 1138, 1142, 1146,
1251, 1256, 1261, 1266, 1271, 1276, 1281, 1286, 1291, 1296, 1151, 1156, 1161, 1166, 1171, 1176, 1181, 1186, 1191, 1196,
1301, 1306, 1311, 1316, 1321, 1326, 1331, 1336, 1341, 1346, 1201, 1206, 1211, 1216, 1221, 1226, 1231, 1236, 1241, 1246,
1351, 1355, 1359, 1363, 1367, 1371, 1375, 1379, 1383, 1387, 1251, 1255, 1259, 1263, 1267, 1271, 1275, 1279, 1283, 1287,
1391, 1395, 1399, 1403, 1407, 1411, 1419, 1427, 1431, 1444, 1291, 1295, 1299, 1303, 1307, 1311, 1319, 1327, 1331, 1344,
1444, 1447, 1447, 1453, 1456, 1472, 1475, 1484, 1488, 1494, 1344, 1347, 1347, 1353, 1356, 1372, 1375, 1384, 1388, 1394,
1501, 1516, 1520, 1524, 1525, 1531, 1532, 1533, 1534, 1535, 1401, 1416, 1420, 1424, 1425, 1431, 1432, 1433, 1434, 1435,
1536, 1537, 1541, 1542, 1542, 1542, 1552, 1553, 1557, 1557, 1436, 1437, 1441, 1442, 1442, 1442, 1452, 1453, 1457, 1457,
1558, 1558, 1563, 1566, 1576, 1579, 1585, 1586, 1590, 1598, 1458, 1458, 1463, 1466, 1476, 1479, 1485, 1486, 1490, 1498,
1602, 1609, 1609, 1616, 1619, 1626, 1631, 1648, 1648, 1653, 1502, 1509, 1509, 1516, 1519, 1526, 1531, 1548, 1548, 1553,
1653, 1660, 1660, 1668, 1671, 1677, 1680, 1686, 1690, 1697, 1553, 1560, 1560, 1568, 1571, 1577, 1580, 1586, 1590, 1597,
1700, 1703, 1706, 1709, 1718, 1722, 1729, 1732, 1738, 1738 1600, 1603, 1606, 1609, 1618, 1622, 1629, 1632, 1638, 1638
}; };
#endif #endif
...@@ -2442,112 +2442,12 @@ yyreduce: ...@@ -2442,112 +2442,12 @@ yyreduce:
case 18: case 18:
{ {
TFunction* fnCall = (yyvsp[0].interm).function; bool fatalError = false;
TOperator op = fnCall->getBuiltInOp(); (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm).function, (yyvsp[0].interm).intermNode, (yylsp[0]), &fatalError);
if (fatalError)
if (op != EOpNull)
{ {
//
// Then this should be a constructor.
// Don't go through the symbol table for constructors.
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (context->constructorErrorCheck((yylsp[0]), (yyvsp[0].interm).intermNode, *fnCall, op, &type)) {
(yyval.interm.intermTypedNode) = 0;
} else {
//
// It's a constructor, of type 'type'.
//
(yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[0].interm).intermNode, &type, op, fnCall, (yylsp[0]));
}
if ((yyval.interm.intermTypedNode) == 0) {
context->recover();
(yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yylsp[0]));
}
(yyval.interm.intermTypedNode)->setType(type);
} else {
//
// Not a constructor. Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
fnCandidate = context->findFunction((yylsp[0]), fnCall, context->shaderVersion, &builtIn);
if (fnCandidate) {
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
context->extensionErrorCheck((yylsp[0]), fnCandidate->getExtension())) {
context->recover();
}
op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) {
//
// A function call mapped to a built-in operation.
//
if (fnCandidate->getParamCount() == 1) {
//
// Treat it like a built-in unary operator.
//
(yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[0].interm).intermNode, (yylsp[0]));
if ((yyval.interm.intermTypedNode) == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>((yyvsp[0].interm).intermNode)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
context->error((yyvsp[0].interm).intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
YYERROR; YYERROR;
} }
const TType& returnType = fnCandidate->getReturnType();
if (returnType.getBasicType() == EbtBool) {
// Bool types should not have precision, so we'll override any precision
// that might have been set by addUnaryMath.
(yyval.interm.intermTypedNode)->setType(returnType);
} else {
// addUnaryMath has set the precision of the node based on the operand.
(yyval.interm.intermTypedNode)->setTypePreservePrecision(returnType);
}
} else {
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator((yyvsp[0].interm).intermAggregate, op, (yylsp[0]));
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
(yyval.interm.intermTypedNode) = aggregate;
// Some built-in functions have out parameters too.
context->functionCallLValueErrorCheck(fnCandidate, aggregate);
}
} else {
// This is a real function call
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator((yyvsp[0].interm).intermAggregate, EOpFunctionCall, (yylsp[0]));
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
(yyval.interm.intermTypedNode) = aggregate;
context->functionCallLValueErrorCheck(fnCandidate, aggregate);
}
} else {
// error message was put out by PaFindFunction()
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
(yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[0]));
context->recover();
}
}
delete fnCall;
} }
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