You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.9 KiB
197 lines
5.9 KiB
//===--------------------------- 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
|
|
|