Home | History | Annotate | Download | only in Mangler
      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 
     33   MangleVisitor(SPIRversion ver, std::stringstream& s) : TypeVisitor(ver), m_stream(s), seqId(0) {
     34   }
     35 
     36 //
     37 // mangle substitution methods
     38 //
     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 
     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 //
     86   MangleError visit(const PrimitiveType* t) {
     87     m_stream << mangledPrimitiveString(t->getPrimitive());
     88     return MANGLE_SUCCESS;
     89   }
     90 
     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 
    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 
    135   MangleError visit(const AtomicType* p) {
    136     m_stream << "U" << "7_Atomic";
    137     return p->getBaseType()->accept(this);
    138   }
    139 
    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 
    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 //
    172   NameMangler::NameMangler(SPIRversion version):m_spir_version(version) {};
    173 
    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