Path: blob/main/contrib/llvm-project/llvm/lib/IR/Mangler.cpp
35233 views
//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Unified name mangler for assembly backends.9//10//===----------------------------------------------------------------------===//1112#include "llvm/IR/Mangler.h"13#include "llvm/ADT/SmallString.h"14#include "llvm/ADT/StringExtras.h"15#include "llvm/ADT/Twine.h"16#include "llvm/Demangle/Demangle.h"17#include "llvm/IR/DataLayout.h"18#include "llvm/IR/DerivedTypes.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/Module.h"21#include "llvm/Support/raw_ostream.h"22#include "llvm/TargetParser/Triple.h"2324using namespace llvm;2526namespace {27enum ManglerPrefixTy {28Default, ///< Emit default string before each symbol.29Private, ///< Emit "private" prefix before each symbol.30LinkerPrivate ///< Emit "linker private" prefix before each symbol.31};32}3334static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName,35ManglerPrefixTy PrefixTy,36const DataLayout &DL, char Prefix) {37SmallString<256> TmpData;38StringRef Name = GVName.toStringRef(TmpData);39assert(!Name.empty() && "getNameWithPrefix requires non-empty name");4041// No need to do anything special if the global has the special "do not42// mangle" flag in the name.43if (Name[0] == '\1') {44OS << Name.substr(1);45return;46}4748if (DL.doNotMangleLeadingQuestionMark() && Name[0] == '?')49Prefix = '\0';5051if (PrefixTy == Private)52OS << DL.getPrivateGlobalPrefix();53else if (PrefixTy == LinkerPrivate)54OS << DL.getLinkerPrivateGlobalPrefix();5556if (Prefix != '\0')57OS << Prefix;5859// If this is a simple string that doesn't need escaping, just append it.60OS << Name;61}6263static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName,64const DataLayout &DL,65ManglerPrefixTy PrefixTy) {66char Prefix = DL.getGlobalPrefix();67return getNameWithPrefixImpl(OS, GVName, PrefixTy, DL, Prefix);68}6970void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,71const DataLayout &DL) {72return getNameWithPrefixImpl(OS, GVName, DL, Default);73}7475void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,76const Twine &GVName, const DataLayout &DL) {77raw_svector_ostream OS(OutName);78char Prefix = DL.getGlobalPrefix();79return getNameWithPrefixImpl(OS, GVName, Default, DL, Prefix);80}8182static bool hasByteCountSuffix(CallingConv::ID CC) {83switch (CC) {84case CallingConv::X86_FastCall:85case CallingConv::X86_StdCall:86case CallingConv::X86_VectorCall:87return true;88default:89return false;90}91}9293/// Microsoft fastcall and stdcall functions require a suffix on their name94/// indicating the number of words of arguments they take.95static void addByteCountSuffix(raw_ostream &OS, const Function *F,96const DataLayout &DL) {97// Calculate arguments size total.98unsigned ArgWords = 0;99100const unsigned PtrSize = DL.getPointerSize();101102for (const Argument &A : F->args()) {103// For the purposes of the byte count suffix, structs returned by pointer104// do not count as function arguments.105if (A.hasStructRetAttr())106continue;107108// 'Dereference' type in case of byval or inalloca parameter attribute.109uint64_t AllocSize = A.hasPassPointeeByValueCopyAttr() ?110A.getPassPointeeByValueCopySize(DL) :111DL.getTypeAllocSize(A.getType());112113// Size should be aligned to pointer size.114ArgWords += alignTo(AllocSize, PtrSize);115}116117OS << '@' << ArgWords;118}119120void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV,121bool CannotUsePrivateLabel) const {122ManglerPrefixTy PrefixTy = Default;123assert(GV != nullptr && "Invalid Global Value");124if (GV->hasPrivateLinkage()) {125if (CannotUsePrivateLabel)126PrefixTy = LinkerPrivate;127else128PrefixTy = Private;129}130131const DataLayout &DL = GV->getDataLayout();132if (!GV->hasName()) {133// Get the ID for the global, assigning a new one if we haven't got one134// already.135unsigned &ID = AnonGlobalIDs[GV];136if (ID == 0)137ID = AnonGlobalIDs.size();138139// Must mangle the global into a unique ID.140getNameWithPrefixImpl(OS, "__unnamed_" + Twine(ID), DL, PrefixTy);141return;142}143144StringRef Name = GV->getName();145char Prefix = DL.getGlobalPrefix();146147// Mangle functions with Microsoft calling conventions specially. Only do148// this mangling for x86_64 vectorcall and 32-bit x86.149const Function *MSFunc = dyn_cast_or_null<Function>(GV->getAliaseeObject());150151// Don't add byte count suffixes when '\01' or '?' are in the first152// character.153if (Name.starts_with("\01") ||154(DL.doNotMangleLeadingQuestionMark() && Name.starts_with("?")))155MSFunc = nullptr;156157CallingConv::ID CC =158MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C;159if (!DL.hasMicrosoftFastStdCallMangling() &&160CC != CallingConv::X86_VectorCall)161MSFunc = nullptr;162if (MSFunc) {163if (CC == CallingConv::X86_FastCall)164Prefix = '@'; // fastcall functions have an @ prefix instead of _.165else if (CC == CallingConv::X86_VectorCall)166Prefix = '\0'; // vectorcall functions have no prefix.167}168169getNameWithPrefixImpl(OS, Name, PrefixTy, DL, Prefix);170171if (!MSFunc)172return;173174// If we are supposed to add a microsoft-style suffix for stdcall, fastcall,175// or vectorcall, add it. These functions have a suffix of @N where N is the176// cumulative byte size of all of the parameters to the function in decimal.177if (CC == CallingConv::X86_VectorCall)178OS << '@'; // vectorcall functions use a double @ suffix.179FunctionType *FT = MSFunc->getFunctionType();180if (hasByteCountSuffix(CC) &&181// "Pure" variadic functions do not receive @0 suffix.182(!FT->isVarArg() || FT->getNumParams() == 0 ||183(FT->getNumParams() == 1 && MSFunc->hasStructRetAttr())))184addByteCountSuffix(OS, MSFunc, DL);185}186187void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,188const GlobalValue *GV,189bool CannotUsePrivateLabel) const {190raw_svector_ostream OS(OutName);191getNameWithPrefix(OS, GV, CannotUsePrivateLabel);192}193194// Check if the name needs quotes to be safe for the linker to interpret.195static bool canBeUnquotedInDirective(char C) {196return isAlnum(C) || C == '_' || C == '@' || C == '#';197}198199static bool canBeUnquotedInDirective(StringRef Name) {200if (Name.empty())201return false;202203// If any of the characters in the string is an unacceptable character, force204// quotes.205for (char C : Name) {206if (!canBeUnquotedInDirective(C))207return false;208}209210return true;211}212213void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,214const Triple &TT, Mangler &Mangler) {215if (GV->hasDLLExportStorageClass() && !GV->isDeclaration()) {216217if (TT.isWindowsMSVCEnvironment())218OS << " /EXPORT:";219else220OS << " -export:";221222bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());223if (NeedQuotes)224OS << "\"";225if (TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) {226std::string Flag;227raw_string_ostream FlagOS(Flag);228Mangler.getNameWithPrefix(FlagOS, GV, false);229FlagOS.flush();230if (Flag[0] == GV->getDataLayout().getGlobalPrefix())231OS << Flag.substr(1);232else233OS << Flag;234} else {235Mangler.getNameWithPrefix(OS, GV, false);236}237if (TT.isWindowsArm64EC()) {238// Use EXPORTAS for mangled ARM64EC symbols.239// FIXME: During LTO, we're invoked prior to the EC lowering pass,240// so symbols are not yet mangled. Emitting the unmangled name241// typically functions correctly; the linker can resolve the export242// with the demangled alias.243if (std::optional<std::string> demangledName =244getArm64ECDemangledFunctionName(GV->getName()))245OS << ",EXPORTAS," << *demangledName;246}247if (NeedQuotes)248OS << "\"";249250if (!GV->getValueType()->isFunctionTy()) {251if (TT.isWindowsMSVCEnvironment())252OS << ",DATA";253else254OS << ",data";255}256}257if (GV->hasHiddenVisibility() && !GV->isDeclaration() && TT.isOSCygMing()) {258259OS << " -exclude-symbols:";260261bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());262if (NeedQuotes)263OS << "\"";264265std::string Flag;266raw_string_ostream FlagOS(Flag);267Mangler.getNameWithPrefix(FlagOS, GV, false);268FlagOS.flush();269if (Flag[0] == GV->getDataLayout().getGlobalPrefix())270OS << Flag.substr(1);271else272OS << Flag;273274if (NeedQuotes)275OS << "\"";276}277}278279void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,280const Triple &T, Mangler &M) {281if (!T.isWindowsMSVCEnvironment())282return;283284OS << " /INCLUDE:";285bool NeedQuotes = GV->hasName() && !canBeUnquotedInDirective(GV->getName());286if (NeedQuotes)287OS << "\"";288M.getNameWithPrefix(OS, GV, false);289if (NeedQuotes)290OS << "\"";291}292293std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) {294if (Name[0] != '?') {295// For non-C++ symbols, prefix the name with "#" unless it's already296// mangled.297if (Name[0] == '#')298return std::nullopt;299return std::optional<std::string>(("#" + Name).str());300}301302// If the name contains $$h, then it is already mangled.303if (Name.contains("$$h"))304return std::nullopt;305306// Ask the demangler where we should insert "$$h".307auto InsertIdx = getArm64ECInsertionPointInMangledName(Name);308if (!InsertIdx)309return std::nullopt;310311return std::optional<std::string>(312(Name.substr(0, *InsertIdx) + "$$h" + Name.substr(*InsertIdx)).str());313}314315std::optional<std::string>316llvm::getArm64ECDemangledFunctionName(StringRef Name) {317if (Name[0] == '#')318return std::optional<std::string>(Name.substr(1));319if (Name[0] != '?')320return std::nullopt;321322std::pair<StringRef, StringRef> Pair = Name.split("$$h");323if (Pair.second.empty())324return std::nullopt;325return std::optional<std::string>((Pair.first + Pair.second).str());326}327328329