| 7851 | } |
| 7852 | |
| 7853 | spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node) |
| 7854 | { |
| 7855 | // Grab the function's pointer from the previously created function |
| 7856 | spv::Function* function = functionMap[node->getName().c_str()]; |
| 7857 | if (! function) |
| 7858 | return 0; |
| 7859 | |
| 7860 | const glslang::TIntermSequence& glslangArgs = node->getSequence(); |
| 7861 | const glslang::TQualifierList& qualifiers = node->getQualifierList(); |
| 7862 | |
| 7863 | // See comments in makeFunctions() for details about the semantics for parameter passing. |
| 7864 | // |
| 7865 | // These imply we need a four step process: |
| 7866 | // 1. Evaluate the arguments |
| 7867 | // 2. Allocate and make copies of in, out, and inout arguments |
| 7868 | // 3. Make the call |
| 7869 | // 4. Copy back the results |
| 7870 | |
| 7871 | // 1. Evaluate the arguments and their types |
| 7872 | std::vector<spv::Builder::AccessChain> lValues; |
| 7873 | std::vector<spv::Id> rValues; |
| 7874 | std::vector<const glslang::TType*> argTypes; |
| 7875 | for (int a = 0; a < (int)glslangArgs.size(); ++a) { |
| 7876 | argTypes.push_back(&glslangArgs[a]->getAsTyped()->getType()); |
| 7877 | // build l-value |
| 7878 | builder.clearAccessChain(); |
| 7879 | glslangArgs[a]->traverse(this); |
| 7880 | // keep outputs and pass-by-originals as l-values, evaluate others as r-values |
| 7881 | if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0) || |
| 7882 | writableParam(qualifiers[a])) { |
| 7883 | // save l-value |
| 7884 | lValues.push_back(builder.getAccessChain()); |
| 7885 | } else { |
| 7886 | // process r-value |
| 7887 | rValues.push_back(accessChainLoad(*argTypes.back())); |
| 7888 | } |
| 7889 | } |
| 7890 | |
| 7891 | // Reset source location to the function call location after argument evaluation |
| 7892 | builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); |
| 7893 | |
| 7894 | // 2. Allocate space for anything needing a copy, and if it's "in" or "inout" |
| 7895 | // copy the original into that space. |
| 7896 | // |
| 7897 | // Also, build up the list of actual arguments to pass in for the call |
| 7898 | int lValueCount = 0; |
| 7899 | int rValueCount = 0; |
| 7900 | std::vector<spv::Id> spvArgs; |
| 7901 | for (int a = 0; a < (int)glslangArgs.size(); ++a) { |
| 7902 | spv::Id arg; |
| 7903 | if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) { |
| 7904 | builder.setAccessChain(lValues[lValueCount]); |
| 7905 | arg = builder.accessChainGetLValue(); |
| 7906 | ++lValueCount; |
| 7907 | } else if (writableParam(qualifiers[a])) { |
| 7908 | // need space to hold the copy |
| 7909 | arg = builder.createVariable(function->getParamPrecision(a), spv::StorageClass::Function, |
| 7910 | builder.getContainedTypeId(function->getParamType(a)), "param"); |
nothing calls this directly
no test coverage detected