1 //===--------------------------- Mangler.cpp -----------------------------===// 2 // 3 // SPIR Tools 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 /* 10 * Contributed by: Intel Corporation. 11 */ 12 13 #include "FunctionDescriptor.h" 14 #include "ManglingUtils.h" 15 #include "NameMangleAPI.h" 16 #include "ParameterType.h" 17 #include "SPIRVInternal.h" 18 #include <algorithm> 19 #include <string> 20 #include <sstream> 21 #include <map> 22 23 // According to IA64 name mangling spec, 24 // builtin vector types should not be substituted 25 // This is a workaround till this gets fixed in CLang 26 #define ENABLE_MANGLER_VECTOR_SUBSTITUTION 1 27 28 namespace SPIR { 29 30 class MangleVisitor: public TypeVisitor { 31 public: 32 MangleVisitor(SPIRversion ver,std::stringstream & s)33 MangleVisitor(SPIRversion ver, std::stringstream& s) : TypeVisitor(ver), m_stream(s), seqId(0) { 34 } 35 36 // 37 // mangle substitution methods 38 // mangleSequenceID(unsigned SeqID)39 void mangleSequenceID(unsigned SeqID) { 40 if (SeqID == 1) 41 m_stream << '0'; 42 else if (SeqID > 1) { 43 std::string bstr; 44 std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 45 SeqID--; 46 bstr.reserve(7); 47 for (; SeqID != 0; SeqID /= 36) 48 bstr += charset.substr(SeqID % 36, 1); 49 std::reverse(bstr.begin(), bstr.end()); 50 m_stream << bstr; 51 } 52 m_stream << '_'; 53 } 54 mangleSubstitution(const ParamType * type,std::string typeStr)55 bool mangleSubstitution(const ParamType* type, std::string typeStr) { 56 size_t fpos; 57 std::stringstream thistypeStr; 58 thistypeStr << typeStr; 59 if ((fpos = m_stream.str().find(typeStr)) != std::string::npos) { 60 const char* nType; 61 if (const PointerType* p = SPIR::dyn_cast<PointerType>(type)) { 62 if ((nType = mangledPrimitiveStringfromName(p->getPointee()->toString()))) 63 thistypeStr << nType; 64 } 65 #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) 66 else if (const VectorType* pVec = SPIR::dyn_cast<VectorType>(type)) { 67 if ((nType = mangledPrimitiveStringfromName(pVec->getScalarType()->toString()))) 68 thistypeStr << nType; 69 } 70 #endif 71 std::map<std::string, unsigned>::iterator I = substitutions.find(thistypeStr.str()); 72 if (I == substitutions.end()) 73 return false; 74 75 unsigned SeqID = I->second; 76 m_stream << 'S'; 77 mangleSequenceID(SeqID); 78 return true; 79 } 80 return false; 81 } 82 83 // 84 // Visit methods 85 // visit(const PrimitiveType * t)86 MangleError visit(const PrimitiveType* t) { 87 m_stream << mangledPrimitiveString(t->getPrimitive()); 88 return MANGLE_SUCCESS; 89 } 90 visit(const PointerType * p)91 MangleError visit(const PointerType* p) { 92 size_t fpos = m_stream.str().size(); 93 std::string qualStr; 94 MangleError me = MANGLE_SUCCESS; 95 for (unsigned int i = ATTR_QUALIFIER_FIRST; i <= ATTR_QUALIFIER_LAST; i++) { 96 TypeAttributeEnum qualifier = (TypeAttributeEnum)i; 97 if (p->hasQualifier(qualifier)) { 98 qualStr += getMangledAttribute(qualifier); 99 } 100 } 101 qualStr += getMangledAttribute((p->getAddressSpace())); 102 if (!mangleSubstitution(p, "P" + qualStr)) { 103 // A pointee type is substituted when it is a user type, a vector type 104 // (but see a comment in the beginning of this file), a pointer type, 105 // or a primitive type with qualifiers (addr. space and/or CV qualifiers). 106 // So, stream "P", type qualifiers 107 m_stream << "P" << qualStr; 108 // and the pointee type itself. 109 me = p->getPointee()->accept(this); 110 // The type qualifiers plus a pointee type is a substitutable entity 111 if(qualStr.length() > 0) 112 substitutions[m_stream.str().substr(fpos + 1)] = seqId++; 113 // The complete pointer type is substitutable as well 114 substitutions[m_stream.str().substr(fpos)] = seqId++; 115 } 116 return me; 117 } 118 visit(const VectorType * v)119 MangleError visit(const VectorType* v) { 120 size_t index = m_stream.str().size(); 121 std::stringstream typeStr; 122 typeStr << "Dv" << v->getLength() << "_"; 123 MangleError me = MANGLE_SUCCESS; 124 #if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION) 125 if (!mangleSubstitution(v, typeStr.str())) 126 #endif 127 { 128 m_stream << typeStr.str(); 129 me = v->getScalarType()->accept(this); 130 substitutions[m_stream.str().substr(index)] = seqId++; 131 } 132 return me; 133 } 134 visit(const AtomicType * p)135 MangleError visit(const AtomicType* p) { 136 m_stream << "U" << "7_Atomic"; 137 return p->getBaseType()->accept(this); 138 } 139 visit(const BlockType * p)140 MangleError visit(const BlockType* p) { 141 m_stream << "U" << "13block_pointerFv"; 142 if (p->getNumOfParams() == 0) 143 m_stream << "v"; 144 else 145 for (unsigned int i=0; i < p->getNumOfParams(); ++i) { 146 MangleError err = p->getParam(i)->accept(this); 147 if (err != MANGLE_SUCCESS) { 148 return err; 149 } 150 } 151 m_stream << "E"; 152 return MANGLE_SUCCESS; 153 } 154 visit(const UserDefinedType * pTy)155 MangleError visit(const UserDefinedType* pTy) { 156 std::string name = pTy->toString(); 157 m_stream << name.size() << name; 158 return MANGLE_SUCCESS; 159 } 160 161 private: 162 163 // Holds the mangled string representing the prototype of the function. 164 std::stringstream& m_stream; 165 unsigned seqId; 166 std::map<std::string, unsigned> substitutions; 167 }; 168 169 // 170 // NameMangler 171 // NameMangler(SPIRversion version)172 NameMangler::NameMangler(SPIRversion version):m_spir_version(version) {}; 173 mangle(const FunctionDescriptor & fd,std::string & mangledName)174 MangleError NameMangler::mangle(const FunctionDescriptor& fd, std::string& mangledName ) { 175 if (fd.isNull()) { 176 mangledName.assign(FunctionDescriptor::nullString()); 177 return MANGLE_NULL_FUNC_DESCRIPTOR; 178 } 179 std::stringstream ret; 180 ret << "_Z" << fd.name.length() << fd.name; 181 MangleVisitor visitor(m_spir_version, ret); 182 for (unsigned int i=0; i < fd.parameters.size(); ++i) { 183 MangleError err = fd.parameters[i]->accept(&visitor); 184 if(err == MANGLE_TYPE_NOT_SUPPORTED) { 185 mangledName.assign("Type "); 186 mangledName.append(fd.parameters[i]->toString()); 187 mangledName.append(" is not supported in "); 188 std::string ver = getSPIRVersionAsString(m_spir_version); 189 mangledName.append(ver); 190 return err; 191 } 192 } 193 mangledName.assign(ret.str()); 194 return MANGLE_SUCCESS; 195 } 196 197 } // End SPIR namespace 198