//===--------------------------- Mangler.cpp -----------------------------===// // // SPIR Tools // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// /* * Contributed by: Intel Corporation. */ #include "FunctionDescriptor.h" #include "ManglingUtils.h" #include "NameMangleAPI.h" #include "ParameterType.h" #include "SPIRVInternal.h" #include #include #include #include // According to IA64 name mangling spec, // builtin vector types should not be substituted // This is a workaround till this gets fixed in CLang #define ENABLE_MANGLER_VECTOR_SUBSTITUTION 1 namespace SPIR { class MangleVisitor: public TypeVisitor { public: MangleVisitor(SPIRversion ver, std::stringstream& s) : TypeVisitor(ver), m_stream(s), seqId(0) { } // // mangle substitution methods // void mangleSequenceID(unsigned SeqID) { if (SeqID == 1) m_stream << '0'; else if (SeqID > 1) { std::string bstr; std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; SeqID--; bstr.reserve(7); for (; SeqID != 0; SeqID /= 36) bstr += charset.substr(SeqID % 36, 1); std::reverse(bstr.begin(), bstr.end()); m_stream << bstr; } m_stream << '_'; } bool mangleSubstitution(const ParamType* type, std::string typeStr) { size_t fpos; std::stringstream thistypeStr; thistypeStr << typeStr; if ((fpos = m_stream.str().find(typeStr)) != std::string::npos) { const char* nType; if (const PointerType* p = SPIR::dyn_cast(type)) { if ((nType = mangledPrimitiveStringfromName(p->getPointee()->toString()))) thistypeStr << nType; } #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) else if (const VectorType* pVec = SPIR::dyn_cast(type)) { if ((nType = mangledPrimitiveStringfromName(pVec->getScalarType()->toString()))) thistypeStr << nType; } #endif std::map::iterator I = substitutions.find(thistypeStr.str()); if (I == substitutions.end()) return false; unsigned SeqID = I->second; m_stream << 'S'; mangleSequenceID(SeqID); return true; } return false; } // // Visit methods // MangleError visit(const PrimitiveType* t) { m_stream << mangledPrimitiveString(t->getPrimitive()); return MANGLE_SUCCESS; } MangleError visit(const PointerType* p) { size_t fpos = m_stream.str().size(); std::string qualStr; MangleError me = MANGLE_SUCCESS; for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { TypeAttributeEnum qualifier = (TypeAttributeEnum)i; if (p->hasQualifier(qualifier)) { qualStr += getMangledAttribute(qualifier); } } qualStr += getMangledAttribute((p->getAddressSpace())); if (!mangleSubstitution(p, "P" + qualStr)) { // A pointee type is substituted when it is a user type, a vector type // (but see a comment in the beginning of this file), a pointer type, // or a primitive type with qualifiers (addr. space and/or CV qualifiers). // So, stream "P", type qualifiers m_stream << "P" << qualStr; // and the pointee type itself. me = p->getPointee()->accept(this); // The type qualifiers plus a pointee type is a substitutable entity if(qualStr.length() > 0) substitutions[m_stream.str().substr(fpos + 1)] = seqId++; // The complete pointer type is substitutable as well substitutions[m_stream.str().substr(fpos)] = seqId++; } return me; } MangleError visit(const VectorType* v) { size_t index = m_stream.str().size(); std::stringstream typeStr; typeStr << "Dv" << v->getLength() << "_"; MangleError me = MANGLE_SUCCESS; #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) if (!mangleSubstitution(v, typeStr.str())) #endif { m_stream << typeStr.str(); me = v->getScalarType()->accept(this); substitutions[m_stream.str().substr(index)] = seqId++; } return me; } MangleError visit(const AtomicType* p) { m_stream << "U" << "7_Atomic"; return p->getBaseType()->accept(this); } MangleError visit(const BlockType* p) { m_stream << "U" << "13block_pointerFv"; if (p->getNumOfParams() == 0) m_stream << "v"; else for (unsigned int i=0; i < p->getNumOfParams(); ++i) { MangleError err = p->getParam(i)->accept(this); if (err != MANGLE_SUCCESS) { return err; } } m_stream << "E"; return MANGLE_SUCCESS; } MangleError visit(const UserDefinedType* pTy) { std::string name = pTy->toString(); m_stream << name.size() << name; return MANGLE_SUCCESS; } private: // Holds the mangled string representing the prototype of the function. std::stringstream& m_stream; unsigned seqId; std::map substitutions; }; // // NameMangler // NameMangler::NameMangler(SPIRversion version):m_spir_version(version) {}; MangleError NameMangler::mangle(const FunctionDescriptor& fd, std::string& mangledName ) { if (fd.isNull()) { mangledName.assign(FunctionDescriptor::nullString()); return MANGLE_NULL_FUNC_DESCRIPTOR; } std::stringstream ret; ret << "_Z" << fd.name.length() << fd.name; MangleVisitor visitor(m_spir_version, ret); for (unsigned int i=0; i < fd.parameters.size(); ++i) { MangleError err = fd.parameters[i]->accept(&visitor); if(err == MANGLE_TYPE_NOT_SUPPORTED) { mangledName.assign("Type "); mangledName.append(fd.parameters[i]->toString()); mangledName.append(" is not supported in "); std::string ver = getSPIRVersionAsString(m_spir_version); mangledName.append(ver); return err; } } mangledName.assign(ret.str()); return MANGLE_SUCCESS; } } // End SPIR namespace