• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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