1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
//===--------------------------- 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 <algorithm>
#include <map>
#include <sstream>
#include <string>
// 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), Stream(S), SeqId(0) {}
//
// mangle substitution methods
//
void mangleSequenceID(unsigned SeqID) {
if (SeqID == 1)
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());
Stream << Bstr;
}
Stream << '_';
}
bool mangleSubstitution(const ParamType *Type, std::string TypeStr) {
size_t Fpos;
std::stringstream ThistypeStr;
ThistypeStr << TypeStr;
if ((Fpos = Stream.str().find(TypeStr)) != std::string::npos) {
const char *NType;
if (const PointerType *P = SPIR::dynCast<PointerType>(Type)) {
ThistypeStr << getPointeeMangling(P->getPointee());
}
#if defined(ENABLE_MANGLER_VECTOR_SUBSTITUTION)
else if (const VectorType *PVec = SPIR::dynCast<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;
Stream << 'S';
mangleSequenceID(SeqID);
return true;
}
return false;
}
//
// Visit methods
//
MangleError visit(const PrimitiveType *T) override {
MangleError Me = MANGLE_SUCCESS;
std::string MangledPrimitive =
std::string(mangledPrimitiveString(T->getPrimitive()));
#if defined(SPIRV_SPIR20_MANGLING_REQUIREMENTS)
Stream << MangledPrimitive;
#else
// Builtin primitives such as int are not substitution candidates, but
// all other primitives are. Even though most of these do not appear
// repeatedly in builtin function signatures, we need to track them in
// the substitution map.
if (T->getPrimitive() >= PRIMITIVE_STRUCT_FIRST) {
if (!mangleSubstitution(T, MangledPrimitive)) {
size_t Index = Stream.str().size();
Stream << MangledPrimitive;
recordSubstitution(Stream.str().substr(Index));
}
} else {
Stream << MangledPrimitive;
}
#endif
return Me;
}
MangleError visit(const PointerType *P) override {
size_t Fpos = Stream.str().size();
MangleError Me = MANGLE_SUCCESS;
std::string AttrMangling = getPointerAttributesMangling(P);
if (!mangleSubstitution(P, "P" + AttrMangling)) {
// 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
Stream << "P" << AttrMangling;
// and the pointee type itself.
Me = P->getPointee()->accept(this);
// The type qualifiers plus a pointee type is a substitutable entity, but
// only when there are qualifiers in the first place.
if (!AttrMangling.empty())
recordSubstitution(Stream.str().substr(Fpos + 1));
// The complete pointer type is substitutable as well
recordSubstitution(Stream.str().substr(Fpos));
}
return Me;
}
MangleError visit(const VectorType *V) override {
size_t Index = 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
{
Stream << TypeStr.str();
Me = V->getScalarType()->accept(this);
recordSubstitution(Stream.str().substr(Index));
}
return Me;
}
MangleError visit(const AtomicType *P) override {
MangleError Me = MANGLE_SUCCESS;
size_t Index = Stream.str().size();
const char *TypeStr = "U7_Atomic";
if (!mangleSubstitution(P, TypeStr)) {
Stream << TypeStr;
Me = P->getBaseType()->accept(this);
recordSubstitution(Stream.str().substr(Index));
}
return Me;
}
MangleError visit(const BlockType *P) override {
Stream << "U"
<< "13block_pointerFv";
if (P->getNumOfParams() == 0)
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;
}
}
Stream << "E";
// "Add" the function type (FvvE) and U13block_pointerFvvE to the
// substitution table. We don't actually substitute this if it's present,
// but since the block type only occurs at most once in any function we care
// about, this should be sufficient.
SeqId += 2;
return MANGLE_SUCCESS;
}
MangleError visit(const UserDefinedType *PTy) override {
size_t Index = Stream.str().size();
std::string Name = PTy->toString();
if (!mangleSubstitution(PTy, Name)) {
Stream << Name.size() << Name;
recordSubstitution(Stream.str().substr(Index));
}
return MANGLE_SUCCESS;
}
private:
void recordSubstitution(const std::string &Str) {
Substitutions[Str] = SeqId++;
}
// Holds the mangled string representing the prototype of the function.
std::stringstream &Stream;
unsigned SeqId;
std::map<std::string, unsigned> Substitutions;
};
//
// NameMangler
//
NameMangler::NameMangler(SPIRversion Version) : SpirVersion(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(SpirVersion, 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(SpirVersion);
MangledName.append(Ver);
return Err;
}
}
MangledName.assign(Ret.str());
return MANGLE_SUCCESS;
}
} // namespace SPIR
|