| Index: src/IceGlobalContext.cpp
|
| diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
|
| index af3e6c7065e657aa98a4c989f89d64c5a120bc28..25a4ab30ff924798a77be47e401ea40b115278e8 100644
|
| --- a/src/IceGlobalContext.cpp
|
| +++ b/src/IceGlobalContext.cpp
|
| @@ -18,6 +18,7 @@
|
| #include "IceCfg.h"
|
| #include "IceCfgNode.h"
|
| #include "IceClFlags.h"
|
| +#include "IceClFlagsExtra.h"
|
| #include "IceDefs.h"
|
| #include "IceELFObjectWriter.h"
|
| #include "IceGlobalInits.h"
|
| @@ -38,8 +39,6 @@
|
| #endif // __clang__
|
|
|
| #include <algorithm> // max()
|
| -#include <cctype> // isdigit(), isupper()
|
| -#include <locale> // locale
|
|
|
| namespace std {
|
| template <> struct hash<Ice::RelocatableTuple> {
|
| @@ -250,9 +249,9 @@ void GlobalContext::CodeStats::dump(const IceString &Name, GlobalContext *Ctx) {
|
| }
|
|
|
| GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
|
| - ELFStreamer *ELFStr, const ClFlags &Flags)
|
| + ELFStreamer *ELFStr)
|
| : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
|
| - StrEmit(OsEmit), StrError(OsError), Flags(Flags), ObjectWriter(),
|
| + StrEmit(OsEmit), StrError(OsError), ObjectWriter(),
|
| OptQ(/*Sequential=*/Flags.isSequential(),
|
| /*MaxSize=*/Flags.getNumTranslationThreads()),
|
| // EmitQ is allowed unlimited size.
|
| @@ -293,15 +292,13 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
|
| // ProfileBlockInfoVarDecl is initialized here because it takes this as a
|
| // parameter -- we want to
|
| // ensure that at least this' member variables are initialized.
|
| - ProfileBlockInfoVarDecl = VariableDeclaration::create(this);
|
| + ProfileBlockInfoVarDecl = VariableDeclaration::createExternal(this);
|
| ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
|
| ProfileBlockInfoVarDecl->setIsConstant(true);
|
|
|
| // Note: if you change this symbol, make sure to update
|
| // runtime/szrt_profiler.c as well.
|
| ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
|
| - ProfileBlockInfoVarDecl->setSuppressMangling();
|
| - ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
|
|
| TargetLowering::staticInit(this);
|
| }
|
| @@ -418,7 +415,7 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
|
| OstreamLocker L(this);
|
| Ostream &Stream = getStrDump();
|
| for (const Ice::VariableDeclaration *Global : Globals) {
|
| - Global->dump(this, Stream);
|
| + Global->dump(Stream);
|
| }
|
| }
|
| if (Flags.getDisableTranslation())
|
| @@ -545,15 +542,15 @@ void GlobalContext::emitItems() {
|
|
|
| std::unique_ptr<Assembler> Asm = Item->getAsm();
|
| Asm->alignFunction();
|
| - IceString MangledName = mangleName(Asm->getFunctionName());
|
| + const IceString &Name = Asm->getFunctionName();
|
| switch (getFlags().getOutFileType()) {
|
| case FT_Elf:
|
| - getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
|
| + getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(),
|
| Asm.get());
|
| break;
|
| case FT_Iasm: {
|
| OstreamLocker L(this);
|
| - Cfg::emitTextHeader(MangledName, this, Asm.get());
|
| + Cfg::emitTextHeader(Name, this, Asm.get());
|
| Asm->emitIASBytes(this);
|
| } break;
|
| case FT_Asm:
|
| @@ -587,169 +584,6 @@ void GlobalContext::emitItems() {
|
| lowerGlobalsIfNoCodeHasBeenSeen();
|
| }
|
|
|
| -// Scan a string for S[0-9A-Z]*_ patterns and replace them with
|
| -// S<num>_ where <num> is the next base-36 value. If a type name
|
| -// legitimately contains that pattern, then the substitution will be
|
| -// made in error and most likely the link will fail. In this case,
|
| -// the test classes can be rewritten not to use that pattern, which is
|
| -// much simpler and more reliable than implementing a full demangling
|
| -// parser. Another substitution-in-error may occur if a type
|
| -// identifier ends with the pattern S[0-9A-Z]*, because an immediately
|
| -// following substitution string like "S1_" or "PS1_" may be combined
|
| -// with the previous type.
|
| -void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
|
| - const std::locale CLocale("C");
|
| - // Provide extra space in case the length of <num> increases.
|
| - ManglerVector NewName(OldName.size() * 2);
|
| - size_t OldPos = 0;
|
| - size_t NewPos = 0;
|
| - size_t OldLen = OldName.size();
|
| - for (; OldPos < OldLen; ++OldPos, ++NewPos) {
|
| - if (OldName[OldPos] == '\0')
|
| - break;
|
| - if (OldName[OldPos] == 'S') {
|
| - // Search forward until we find _ or invalid character (including \0).
|
| - bool AllZs = true;
|
| - bool Found = false;
|
| - size_t Last;
|
| - for (Last = OldPos + 1; Last < OldLen; ++Last) {
|
| - char Ch = OldName[Last];
|
| - if (Ch == '_') {
|
| - Found = true;
|
| - break;
|
| - } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) {
|
| - if (Ch != 'Z')
|
| - AllZs = false;
|
| - } else {
|
| - // Invalid character, stop searching.
|
| - break;
|
| - }
|
| - }
|
| - if (Found) {
|
| - NewName[NewPos++] = OldName[OldPos++]; // 'S'
|
| - size_t Length = Last - OldPos;
|
| - // NewPos and OldPos point just past the 'S'.
|
| - assert(NewName[NewPos - 1] == 'S');
|
| - assert(OldName[OldPos - 1] == 'S');
|
| - assert(OldName[OldPos + Length] == '_');
|
| - if (AllZs) {
|
| - // Replace N 'Z' characters with a '0' (if N=0) or '1' (if N>0)
|
| - // followed by N '0' characters.
|
| - NewName[NewPos++] = (Length ? '1' : '0');
|
| - for (size_t i = 0; i < Length; ++i) {
|
| - NewName[NewPos++] = '0';
|
| - }
|
| - } else {
|
| - // Iterate right-to-left and increment the base-36 number.
|
| - bool Carry = true;
|
| - for (size_t i = 0; i < Length; ++i) {
|
| - size_t Offset = Length - 1 - i;
|
| - char Ch = OldName[OldPos + Offset];
|
| - if (Carry) {
|
| - Carry = false;
|
| - switch (Ch) {
|
| - case '9':
|
| - Ch = 'A';
|
| - break;
|
| - case 'Z':
|
| - Ch = '0';
|
| - Carry = true;
|
| - break;
|
| - default:
|
| - ++Ch;
|
| - break;
|
| - }
|
| - }
|
| - NewName[NewPos + Offset] = Ch;
|
| - }
|
| - NewPos += Length;
|
| - }
|
| - OldPos = Last;
|
| - // Fall through and let the '_' be copied across.
|
| - }
|
| - }
|
| - NewName[NewPos] = OldName[OldPos];
|
| - }
|
| - assert(NewName[NewPos] == '\0');
|
| - OldName = NewName;
|
| -}
|
| -
|
| -// In this context, name mangling means to rewrite a symbol using a given
|
| -// prefix. For a C++ symbol, nest the original symbol inside the "prefix"
|
| -// namespace. For other symbols, just prepend the prefix.
|
| -IceString GlobalContext::mangleName(const IceString &Name) const {
|
| - // An already-nested name like foo::bar() gets pushed down one level, making
|
| - // it equivalent to Prefix::foo::bar().
|
| - // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
|
| - // A non-nested but mangled name like bar() gets nested, making it equivalent
|
| - // to Prefix::bar().
|
| - // _Z3barxyz ==> ZN6Prefix3barExyz
|
| - // An unmangled, extern "C" style name, gets a simple prefix:
|
| - // bar ==> Prefixbar
|
| - if (!BuildDefs::dump() || getFlags().getTestPrefix().empty())
|
| - return Name;
|
| -
|
| - const IceString &TestPrefix = getFlags().getTestPrefix();
|
| - unsigned PrefixLength = TestPrefix.length();
|
| - ManglerVector NameBase(1 + Name.length());
|
| - const size_t BufLen = 30 + Name.length() + PrefixLength;
|
| - ManglerVector NewName(BufLen);
|
| - uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
|
| -
|
| - int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
|
| - if (ItemsParsed == 1) {
|
| - // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
|
| - // (splice in "6Prefix") ^^^^^^^
|
| - snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
|
| - TestPrefix.c_str(), NameBase.data());
|
| - // We ignore the snprintf return value (here and below). If we somehow
|
| - // miscalculated the output buffer length, the output will be truncated,
|
| - // but it will be truncated consistently for all mangleName() calls on the
|
| - // same input string.
|
| - incrementSubstitutions(NewName);
|
| - return NewName.data();
|
| - }
|
| -
|
| - // Artificially limit BaseLength to 9 digits (less than 1 billion) because
|
| - // sscanf behavior is undefined on integer overflow. If there are more than 9
|
| - // digits (which we test by looking at the beginning of NameBase), then we
|
| - // consider this a failure to parse a namespace mangling, and fall back to
|
| - // the simple prefixing.
|
| - ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
|
| - if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
|
| - !isdigit(NameBase[0])) {
|
| - // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
|
| - // ^^^^^^^^ ^
|
| - // (splice in "N6Prefix", and insert "E" after "3bar") But an "I" after the
|
| - // identifier indicates a template argument list terminated with "E";
|
| - // insert the new "E" before/after the old "E". E.g.:
|
| - // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
|
| - // ^^^^^^^^ ^
|
| - // (splice in "N6Prefix", and insert "E" after "3barIabcE")
|
| - ManglerVector OrigName(Name.length());
|
| - ManglerVector OrigSuffix(Name.length());
|
| - uint32_t ActualBaseLength = BaseLength;
|
| - if (NameBase[ActualBaseLength] == 'I') {
|
| - ++ActualBaseLength;
|
| - while (NameBase[ActualBaseLength] != 'E' &&
|
| - NameBase[ActualBaseLength] != '\0')
|
| - ++ActualBaseLength;
|
| - }
|
| - strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
|
| - OrigName[ActualBaseLength] = '\0';
|
| - strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
|
| - snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
|
| - TestPrefix.c_str(), BaseLength, OrigName.data(),
|
| - OrigSuffix.data());
|
| - incrementSubstitutions(NewName);
|
| - return NewName.data();
|
| - }
|
| -
|
| - // Transform bar ==> Prefixbar
|
| - // ^^^^^^
|
| - return TestPrefix + Name;
|
| -}
|
| -
|
| GlobalContext::~GlobalContext() {
|
| llvm::DeleteContainerPointers(AllThreadContexts);
|
| LockedPtr<DestructorArray> Dtors = getDestructors();
|
| @@ -812,25 +646,21 @@ Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
|
| Constant *GlobalContext::getConstantSym(const RelocOffsetT Offset,
|
| const RelocOffsetArray &OffsetExpr,
|
| const IceString &Name,
|
| - const IceString &EmitString,
|
| - bool SuppressMangling) {
|
| + const IceString &EmitString) {
|
| return getConstPool()->Relocatables.getOrAdd(
|
| - this,
|
| - RelocatableTuple(Offset, OffsetExpr, Name, EmitString, SuppressMangling));
|
| + this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString));
|
| }
|
|
|
| Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
|
| - const IceString &Name,
|
| - bool SuppressMangling) {
|
| + const IceString &Name) {
|
| constexpr char EmptyEmitString[] = "";
|
| - return getConstantSym(Offset, {}, Name, EmptyEmitString, SuppressMangling);
|
| + return getConstantSym(Offset, {}, Name, EmptyEmitString);
|
| }
|
|
|
| Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
|
| constexpr RelocOffsetT Offset = 0;
|
| - constexpr bool SuppressMangling = true;
|
| return getConstPool()->ExternRelocatables.getOrAdd(
|
| - this, RelocatableTuple(Offset, {}, Name, SuppressMangling));
|
| + this, RelocatableTuple(Offset, {}, Name));
|
| }
|
|
|
| Constant *GlobalContext::getConstantUndef(Type Ty) {
|
| @@ -937,7 +767,7 @@ JumpTableDataList GlobalContext::getJumpTables() {
|
| }
|
|
|
| JumpTableData &
|
| -GlobalContext::addJumpTable(IceString FuncName, SizeT Id,
|
| +GlobalContext::addJumpTable(const IceString &FuncName, SizeT Id,
|
| const JumpTableData::TargetList &TargetList) {
|
| auto JumpTableList = getJumpTableList();
|
| JumpTableList->emplace_back(FuncName, Id, TargetList);
|
| @@ -1030,6 +860,9 @@ void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
|
| Timers->at(StackID).dump(getStrDump(), DumpCumulative);
|
| }
|
|
|
| +ClFlags GlobalContext::Flags;
|
| +ClFlagsExtra GlobalContext::ExtraFlags;
|
| +
|
| void TimerMarker::push() {
|
| switch (StackID) {
|
| case GlobalContext::TSK_Default:
|
|
|