Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

231 lines
7.2 KiB
C++

//===--------------------------- 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 <sstream>
#include <string>
#include <unordered_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), 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::unordered_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::unordered_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