Handle seeing function call syntax in the grammar, which could be any of - .length() method - constructor - a call to a built-in function mapped to an operator - a call to a built-in function that will remain a function call (e.g., texturing) - user function - subroutine call (not implemented yet)
| 1380 | // - subroutine call (not implemented yet) |
| 1381 | // |
| 1382 | TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) |
| 1383 | { |
| 1384 | TIntermTyped* result = nullptr; |
| 1385 | |
| 1386 | if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) { |
| 1387 | // allow calls that are invalid in Vulkan Semantics to be invisibily |
| 1388 | // remapped to equivalent valid functions |
| 1389 | result = vkRelaxedRemapFunctionCall(loc, function, arguments); |
| 1390 | if (result) |
| 1391 | return result; |
| 1392 | } |
| 1393 | |
| 1394 | if (function->getBuiltInOp() == EOpArrayLength) |
| 1395 | result = handleLengthMethod(loc, function, arguments); |
| 1396 | else if (function->getBuiltInOp() != EOpNull) { |
| 1397 | // |
| 1398 | // Then this should be a constructor. |
| 1399 | // Don't go through the symbol table for constructors. |
| 1400 | // Their parameters will be verified algorithmically. |
| 1401 | // |
| 1402 | TType type(EbtVoid); // use this to get the type back |
| 1403 | if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) { |
| 1404 | // |
| 1405 | // It's a constructor, of type 'type'. |
| 1406 | // |
| 1407 | result = addConstructor(loc, arguments, type); |
| 1408 | if (result == nullptr) |
| 1409 | error(loc, "cannot construct with these arguments", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str(), ""); |
| 1410 | } |
| 1411 | } else { |
| 1412 | // |
| 1413 | // Find it in the symbol table. |
| 1414 | // |
| 1415 | const TFunction* fnCandidate; |
| 1416 | bool builtIn {false}; |
| 1417 | fnCandidate = findFunction(loc, *function, builtIn); |
| 1418 | if (fnCandidate) { |
| 1419 | // This is a declared function that might map to |
| 1420 | // - a built-in operator, |
| 1421 | // - a built-in function not mapped to an operator, or |
| 1422 | // - a user function. |
| 1423 | |
| 1424 | // Error check for a function requiring specific extensions present. |
| 1425 | if (builtIn && |
| 1426 | (fnCandidate->getBuiltInOp() == EOpSubgroupQuadAll || fnCandidate->getBuiltInOp() == EOpSubgroupQuadAny)) |
| 1427 | requireExtensions(loc, 1, &E_GL_EXT_shader_quad_control, fnCandidate->getName().c_str()); |
| 1428 | |
| 1429 | if (builtIn && fnCandidate->getNumExtensions()) |
| 1430 | requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); |
| 1431 | |
| 1432 | if (builtIn && fnCandidate->getType().contains16BitFloat()) |
| 1433 | requireFloat16Arithmetic(loc, "built-in function", "float16 types can only be in uniform block or buffer storage"); |
| 1434 | if (builtIn && fnCandidate->getType().contains16BitInt()) |
| 1435 | requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage"); |
| 1436 | if (builtIn && fnCandidate->getType().contains8BitInt()) |
| 1437 | requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage"); |
| 1438 | if (builtIn && (fnCandidate->getBuiltInOp() == EOpTextureFetch || fnCandidate->getBuiltInOp() == EOpTextureQuerySize)) { |
| 1439 | if ((*fnCandidate)[0].type->getSampler().isMultiSample() && version <= 140) |
no test coverage detected