C++程序  |  198行  |  5.95 KB

//===--------------------------- 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 <algorithm>
#include <string>
#include <sstream>
#include <map>

// 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<PointerType>(type)) {
        if ((nType = mangledPrimitiveStringfromName(p->getPointee()->toString())))
          thistypeStr << nType;
      }
#if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION)
      else if (const VectorType* pVec = SPIR::dyn_cast<VectorType>(type)) {
        if ((nType = mangledPrimitiveStringfromName(pVec->getScalarType()->toString())))
          thistypeStr << nType;
      }
#endif
      std::map<std::string, unsigned>::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<std::string, unsigned> 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