Commit b3ff42cd by Alexis Hetu Committed by Alexis Hétu

Moved function creation code from glslang.y to TParseContext.

Added TParseContext::addFunctionCallOrMethod() to move function creation functionality out of glslang.y. Change-Id: Ia23e8c2490ba9d2bb1fcd00a1ef06eab5cf60b80 Reviewed-on: https://swiftshader-review.googlesource.com/3640Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 824e7b3e
...@@ -3249,6 +3249,160 @@ TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, ...@@ -3249,6 +3249,160 @@ 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 *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError)
{
*fatalError = false;
TOperator op = fnCall->getBuiltInOp();
TIntermTyped *callNode = nullptr;
if(thisNode != nullptr)
{
ConstantUnion *unionArray = new ConstantUnion[1];
int arraySize = 0;
TIntermTyped *typedThis = thisNode->getAsTyped();
if(fnCall->getName() != "length")
{
error(loc, "invalid method", fnCall->getName().c_str());
recover();
}
else if(paramNode != nullptr)
{
error(loc, "method takes no parameters", "length");
recover();
}
else if(typedThis == nullptr || !typedThis->isArray())
{
error(loc, "length can only be called on arrays", "length");
recover();
}
else
{
arraySize = typedThis->getArraySize();
if(typedThis->getAsSymbolNode() == nullptr)
{
// This code path can be hit with expressions like these:
// (a = b).length()
// (func()).length()
// (int[3](0, 1, 2)).length()
// ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid expression.
// It allows "An array name with the length method applied" in contrast to GLSL 4.4 spec section 5.9
// which allows "An array, vector or matrix expression with the length method applied".
error(loc, "length can only be called on array names, not on array expressions", "length");
recover();
}
}
unionArray->setIConst(arraySize);
callNode = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), loc);
}
else 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, paramNode, *fnCall, op, &type))
{
//
// It's a constructor, of type 'type'.
//
callNode = addConstructor(paramNode, &type, op, fnCall, loc);
}
if(callNode == nullptr)
{
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, &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 = createUnaryMath(op, paramNode->getAsTyped(), loc, &fnCandidate->getReturnType());
if(callNode == nullptr)
{
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: "
<< static_cast<TIntermTyped*>(paramNode)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
error(paramNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
*fatalError = true;
return nullptr;
}
}
else
{
TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, op, loc);
aggregate->setType(fnCandidate->getReturnType());
// Some built-in functions have out parameters too.
functionCallLValueErrorCheck(fnCandidate, aggregate);
callNode = aggregate;
}
}
else
{
// This is a real function call
TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, 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());
callNode = aggregate;
functionCallLValueErrorCheck(fnCandidate, aggregate);
}
callNode->setType(fnCandidate->getReturnType());
}
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, EvqConstExpr), loc);
recover();
}
}
delete fnCall;
return callNode;
}
// //
// Parse an array of strings using yyparse. // Parse an array of strings using yyparse.
// //
......
...@@ -221,6 +221,8 @@ public: ...@@ -221,6 +221,8 @@ public:
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 *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError);
private: private:
bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
......
...@@ -293,101 +293,12 @@ integer_expression ...@@ -293,101 +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, nullptr, @1, &fatalError);
if (fatalError)
if (op != EOpNull)
{ {
// YYERROR;
// 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, &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, 0);
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;
}
} else {
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
}
} else {
// This is a real function call
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
$$->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)
$$->getAsAggregate()->setUserDefined();
$$->getAsAggregate()->setName(fnCandidate->getMangledName());
TQualifier qual;
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
qual = fnCandidate->getParam(i).type->getQualifier();
if (qual == EvqOut || qual == EvqInOut) {
if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
context->recover();
}
}
}
}
$$->setType(fnCandidate->getReturnType());
} 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, EvqConstExpr), @1);
context->recover();
}
} }
delete fnCall;
} }
; ;
......
...@@ -766,33 +766,33 @@ static const yytype_int16 yyrhs[] = ...@@ -766,33 +766,33 @@ static const yytype_int16 yyrhs[] =
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 202, 202, 237, 240, 245, 250, 255, 260, 266, 0, 202, 202, 237, 240, 245, 250, 255, 260, 266,
269, 272, 275, 278, 281, 287, 295, 395, 398, 406, 269, 272, 275, 278, 281, 287, 295, 306, 309, 317,
410, 417, 421, 428, 434, 443, 451, 457, 464, 474, 321, 328, 332, 339, 345, 354, 362, 368, 375, 385,
477, 487, 497, 519, 520, 521, 522, 530, 531, 535, 388, 398, 408, 430, 431, 432, 433, 441, 442, 446,
539, 547, 548, 551, 557, 558, 562, 569, 570, 573, 450, 458, 459, 462, 468, 469, 473, 480, 481, 484,
576, 579, 585, 586, 589, 595, 596, 603, 604, 611, 487, 490, 496, 497, 500, 506, 507, 514, 515, 522,
612, 619, 620, 626, 627, 633, 634, 640, 641, 658, 523, 530, 531, 537, 538, 544, 545, 551, 552, 569,
659, 667, 668, 669, 670, 672, 673, 674, 676, 678, 570, 578, 579, 580, 581, 583, 584, 585, 587, 589,
680, 682, 687, 690, 701, 709, 717, 744, 750, 757, 591, 593, 598, 601, 612, 620, 628, 655, 661, 668,
761, 765, 769, 776, 814, 817, 824, 832, 853, 874, 672, 676, 680, 687, 725, 728, 735, 743, 764, 785,
885, 914, 919, 929, 934, 944, 947, 950, 953, 959, 796, 825, 830, 840, 845, 855, 858, 861, 864, 870,
966, 969, 973, 977, 982, 987, 994, 998, 1002, 1006, 877, 880, 884, 888, 893, 898, 905, 909, 913, 917,
1011, 1016, 1020, 1096, 1106, 1112, 1115, 1121, 1127, 1134, 922, 927, 931, 1007, 1017, 1023, 1026, 1032, 1038, 1045,
1143, 1152, 1155, 1158, 1165, 1169, 1176, 1180, 1185, 1190, 1054, 1063, 1066, 1069, 1076, 1080, 1087, 1091, 1096, 1101,
1200, 1210, 1219, 1229, 1236, 1239, 1242, 1248, 1255, 1258, 1111, 1121, 1130, 1140, 1147, 1150, 1153, 1159, 1166, 1169,
1264, 1267, 1270, 1276, 1279, 1284, 1299, 1303, 1307, 1311, 1175, 1178, 1181, 1187, 1190, 1195, 1210, 1214, 1218, 1222,
1315, 1319, 1324, 1329, 1334, 1339, 1344, 1349, 1354, 1359, 1226, 1230, 1235, 1240, 1245, 1250, 1255, 1260, 1265, 1270,
1364, 1369, 1374, 1379, 1385, 1391, 1397, 1403, 1409, 1415, 1275, 1280, 1285, 1290, 1296, 1302, 1308, 1314, 1320, 1326,
1421, 1427, 1433, 1438, 1443, 1452, 1457, 1462, 1467, 1472, 1332, 1338, 1344, 1349, 1354, 1363, 1368, 1373, 1378, 1383,
1477, 1482, 1487, 1492, 1497, 1502, 1507, 1512, 1517, 1522, 1388, 1393, 1398, 1403, 1408, 1413, 1418, 1423, 1428, 1433,
1535, 1535, 1538, 1538, 1544, 1547, 1563, 1566, 1575, 1579, 1446, 1446, 1449, 1449, 1455, 1458, 1474, 1477, 1486, 1490,
1585, 1592, 1607, 1611, 1615, 1616, 1622, 1623, 1624, 1625, 1496, 1503, 1518, 1522, 1526, 1527, 1533, 1534, 1535, 1536,
1626, 1627, 1628, 1632, 1633, 1633, 1633, 1643, 1644, 1648, 1537, 1538, 1539, 1543, 1544, 1544, 1544, 1554, 1555, 1559,
1648, 1649, 1649, 1654, 1657, 1667, 1670, 1676, 1677, 1681, 1559, 1560, 1560, 1565, 1568, 1578, 1581, 1587, 1588, 1592,
1689, 1693, 1700, 1700, 1707, 1710, 1719, 1724, 1741, 1741, 1600, 1604, 1611, 1611, 1618, 1621, 1630, 1635, 1652, 1652,
1746, 1746, 1753, 1753, 1761, 1764, 1770, 1773, 1779, 1783, 1657, 1657, 1664, 1664, 1672, 1675, 1681, 1684, 1690, 1694,
1790, 1793, 1796, 1799, 1802, 1811, 1815, 1822, 1825, 1831, 1701, 1704, 1707, 1710, 1713, 1722, 1726, 1733, 1736, 1742,
1831 1742
}; };
#endif #endif
...@@ -2625,101 +2625,12 @@ yyreduce: ...@@ -2625,101 +2625,12 @@ yyreduce:
case 16: case 16:
{ {
TFunction* fnCall = (yyvsp[(1) - (1)].interm).function; bool fatalError = false;
TOperator op = fnCall->getBuiltInOp(); (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[(1) - (1)].interm).function, (yyvsp[(1) - (1)].interm).intermNode, nullptr, (yylsp[(1) - (1)]), &fatalError);
if (fatalError)
if (op != EOpNull)
{ {
// YYERROR;
// 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[(1) - (1)]), (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) {
(yyval.interm.intermTypedNode) = 0;
} else {
//
// It's a constructor, of type 'type'.
//
(yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yylsp[(1) - (1)]));
}
if ((yyval.interm.intermTypedNode) == 0) {
context->recover();
(yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yylsp[(1) - (1)]));
}
(yyval.interm.intermTypedNode)->setType(type);
} else {
//
// Not a constructor. Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
fnCandidate = context->findFunction((yylsp[(1) - (1)]), fnCall, &builtIn);
if (fnCandidate) {
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
context->extensionErrorCheck((yylsp[(1) - (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.
//
(yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, 0);
if ((yyval.interm.intermTypedNode) == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
YYERROR;
}
} else {
(yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yylsp[(1) - (1)]));
}
} else {
// This is a real function call
(yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yylsp[(1) - (1)]));
(yyval.interm.intermTypedNode)->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)
(yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined();
(yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName());
TQualifier qual;
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
qual = fnCandidate->getParam(i).type->getQualifier();
if (qual == EvqOut || qual == EvqInOut) {
if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) {
context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
context->recover();
}
}
}
}
(yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
} 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, EvqConstExpr), (yylsp[(1) - (1)]));
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