summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/LTO/LTO.cpp212
-rw-r--r--llvm/lib/Object/CMakeLists.txt1
-rw-r--r--llvm/lib/Object/IRSymtab.cpp228
3 files changed, 127 insertions, 314 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4885f65e3d2..f3d258e6c25 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -305,6 +305,14 @@ void llvm::thinLTOInternalizeAndPromoteInIndex(
thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
}
+struct InputFile::InputModule {
+ BitcodeModule BM;
+ std::unique_ptr<Module> Mod;
+
+ // The range of ModuleSymbolTable entries for this input module.
+ size_t SymBegin, SymEnd;
+};
+
// Requires a destructor for std::vector<InputModule>.
InputFile::~InputFile() = default;
@@ -325,51 +333,87 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
return make_error<StringError>("Bitcode file does not contain any modules",
inconvertibleErrorCode());
- File->Mods = *BMsOrErr;
-
- LLVMContext Ctx;
- std::vector<Module *> Mods;
- std::vector<std::unique_ptr<Module>> OwnedMods;
+ // Create an InputModule for each module in the InputFile, and add it to the
+ // ModuleSymbolTable.
for (auto BM : *BMsOrErr) {
Expected<std::unique_ptr<Module>> MOrErr =
- BM.getLazyModule(Ctx, /*ShouldLazyLoadMetadata*/ true,
+ BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true,
/*IsImporting*/ false);
if (!MOrErr)
return MOrErr.takeError();
- if ((*MOrErr)->getDataLayoutStr().empty())
- return make_error<StringError>("input module has no datalayout",
- inconvertibleErrorCode());
+ size_t SymBegin = File->SymTab.symbols().size();
+ File->SymTab.addModule(MOrErr->get());
+ size_t SymEnd = File->SymTab.symbols().size();
- Mods.push_back(MOrErr->get());
- OwnedMods.push_back(std::move(*MOrErr));
- }
+ for (const auto &C : (*MOrErr)->getComdatSymbolTable()) {
+ auto P = File->ComdatMap.insert(
+ std::make_pair(&C.second, File->Comdats.size()));
+ assert(P.second);
+ (void)P;
+ File->Comdats.push_back(C.first());
+ }
- SmallVector<char, 0> Symtab;
- if (Error E = irsymtab::build(Mods, Symtab, File->Strtab))
- return std::move(E);
-
- irsymtab::Reader R({Symtab.data(), Symtab.size()},
- {File->Strtab.data(), File->Strtab.size()});
- File->SourceFileName = R.getSourceFileName();
- File->COFFLinkerOpts = R.getCOFFLinkerOpts();
- File->ComdatTable = R.getComdatTable();
-
- for (unsigned I = 0; I != Mods.size(); ++I) {
- size_t Begin = File->Symbols.size();
- for (const irsymtab::Reader::SymbolRef &Sym : R.module_symbols(I))
- // Skip symbols that are irrelevant to LTO. Note that this condition needs
- // to match the one in Skip() in LTO::addRegularLTO().
- if (Sym.isGlobal() && !Sym.isFormatSpecific())
- File->Symbols.push_back(Sym);
- File->ModuleSymIndices.push_back({Begin, File->Symbols.size()});
+ File->Mods.push_back({BM, std::move(*MOrErr), SymBegin, SymEnd});
}
return std::move(File);
}
+Expected<int> InputFile::Symbol::getComdatIndex() const {
+ if (!isGV())
+ return -1;
+ const GlobalObject *GO = getGV()->getBaseObject();
+ if (!GO)
+ return make_error<StringError>("Unable to determine comdat of alias!",
+ inconvertibleErrorCode());
+ if (const Comdat *C = GO->getComdat()) {
+ auto I = File->ComdatMap.find(C);
+ assert(I != File->ComdatMap.end());
+ return I->second;
+ }
+ return -1;
+}
+
+Expected<std::string> InputFile::getLinkerOpts() {
+ std::string LinkerOpts;
+ raw_string_ostream LOS(LinkerOpts);
+ // Extract linker options from module metadata.
+ for (InputModule &Mod : Mods) {
+ std::unique_ptr<Module> &M = Mod.Mod;
+ if (auto E = M->materializeMetadata())
+ return std::move(E);
+ if (Metadata *Val = M->getModuleFlag("Linker Options")) {
+ MDNode *LinkerOptions = cast<MDNode>(Val);
+ for (const MDOperand &MDOptions : LinkerOptions->operands())
+ for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
+ LOS << " " << cast<MDString>(MDOption)->getString();
+ }
+ }
+
+ // Synthesize export flags for symbols with dllexport storage.
+ const Triple TT(Mods[0].Mod->getTargetTriple());
+ Mangler M;
+ for (const ModuleSymbolTable::Symbol &Sym : SymTab.symbols())
+ if (auto *GV = Sym.dyn_cast<GlobalValue*>())
+ emitLinkerFlagsForGlobalCOFF(LOS, GV, TT, M);
+ LOS.flush();
+ return LinkerOpts;
+}
+
StringRef InputFile::getName() const {
- return Mods[0].getModuleIdentifier();
+ return Mods[0].BM.getModuleIdentifier();
+}
+
+StringRef InputFile::getSourceFileName() const {
+ return Mods[0].Mod->getSourceFileName();
+}
+
+iterator_range<InputFile::symbol_iterator>
+InputFile::module_symbols(InputModule &IM) {
+ return llvm::make_range(
+ symbol_iterator(SymTab.symbols().data() + IM.SymBegin, SymTab, this),
+ symbol_iterator(SymTab.symbols().data() + IM.SymEnd, SymTab, this));
}
LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
@@ -393,17 +437,21 @@ LTO::LTO(Config Conf, ThinBackend Backend,
LTO::~LTO() = default;
// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym,
+void LTO::addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
+ const InputFile::Symbol &Sym,
SymbolResolution Res, unsigned Partition) {
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
- GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
- if (Res.Prevailing)
- GlobalRes.IRName = Sym.getIRName();
+ GlobalValue *GV = Sym.isGV() ? Sym.getGV() : nullptr;
+ auto &GlobalRes = GlobalResolutions[Sym.getName()];
+ if (GV) {
+ GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
+ if (Res.Prevailing)
+ GlobalRes.IRName = GV->getName();
+ }
// Set the partition to external if we know it is used elsewhere, e.g.
// it is visible to a regular object, is referenced from llvm.compiler_used,
// or was already recorded as being referenced from a different partition.
- if (Res.VisibleToRegularObj || Sym.isUsed() ||
+ if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
(GlobalRes.Partition != GlobalResolution::Unknown &&
GlobalRes.Partition != Partition)) {
GlobalRes.Partition = GlobalResolution::External;
@@ -447,32 +495,41 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);
const SymbolResolution *ResI = Res.begin();
- for (unsigned I = 0; I != Input->Mods.size(); ++I)
- if (Error Err = addModule(*Input, I, ResI, Res.end()))
+ for (InputFile::InputModule &IM : Input->Mods)
+ if (Error Err = addModule(*Input, IM, ResI, Res.end()))
return Err;
assert(ResI == Res.end());
return Error::success();
}
-Error LTO::addModule(InputFile &Input, unsigned ModI,
+Error LTO::addModule(InputFile &Input, InputFile::InputModule &IM,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
- Expected<bool> HasThinLTOSummary = Input.Mods[ModI].hasSummary();
+ // FIXME: move to backend
+ Module &M = *IM.Mod;
+
+ if (M.getDataLayoutStr().empty())
+ return make_error<StringError>("input module has no datalayout",
+ inconvertibleErrorCode());
+
+ if (!Conf.OverrideTriple.empty())
+ M.setTargetTriple(Conf.OverrideTriple);
+ else if (M.getTargetTriple().empty())
+ M.setTargetTriple(Conf.DefaultTriple);
+
+ Expected<bool> HasThinLTOSummary = IM.BM.hasSummary();
if (!HasThinLTOSummary)
return HasThinLTOSummary.takeError();
- auto ModSyms = Input.module_symbols(ModI);
if (*HasThinLTOSummary)
- return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ return addThinLTO(IM.BM, M, Input.module_symbols(IM), ResI, ResE);
else
- return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ return addRegularLTO(IM.BM, ResI, ResE);
}
// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
+Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
if (!RegularLTO.CombinedModule) {
RegularLTO.CombinedModule =
@@ -493,6 +550,9 @@ Error LTO::addRegularLTO(BitcodeModule BM,
ModuleSymbolTable SymTab;
SymTab.addModule(&M);
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
+
std::vector<GlobalValue *> Keep;
for (GlobalVariable &GV : M.globals())
@@ -504,35 +564,17 @@ Error LTO::addRegularLTO(BitcodeModule BM,
if (GlobalObject *GO = GA.getBaseObject())
AliasedGlobals.insert(GO);
- // In this function we need IR GlobalValues matching the symbols in Syms
- // (which is not backed by a module), so we need to enumerate them in the same
- // order. The symbol enumeration order of a ModuleSymbolTable intentionally
- // matches the order of an irsymtab, but when we read the irsymtab in
- // InputFile::create we omit some symbols that are irrelevant to LTO. The
- // Skip() function skips the same symbols from the module as InputFile does
- // from the symbol table.
- auto MsymI = SymTab.symbols().begin(), MsymE = SymTab.symbols().end();
- auto Skip = [&]() {
- while (MsymI != MsymE) {
- auto Flags = SymTab.getSymbolFlags(*MsymI);
- if ((Flags & object::BasicSymbolRef::SF_Global) &&
- !(Flags & object::BasicSymbolRef::SF_FormatSpecific))
- return;
- ++MsymI;
- }
- };
- Skip();
-
- for (const InputFile::Symbol &Sym : Syms) {
+ for (const InputFile::Symbol &Sym :
+ make_range(InputFile::symbol_iterator(SymTab.symbols().begin(), SymTab,
+ nullptr),
+ InputFile::symbol_iterator(SymTab.symbols().end(), SymTab,
+ nullptr))) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, 0);
+ addSymbolToGlobalRes(Used, Sym, Res, 0);
- assert(MsymI != MsymE);
- ModuleSymbolTable::Symbol Msym = *MsymI++;
- Skip();
-
- if (GlobalValue *GV = Msym.dyn_cast<GlobalValue *>()) {
+ if (Sym.isGV()) {
+ GlobalValue *GV = Sym.getGV();
if (Res.Prevailing) {
if (Sym.isUndefined())
continue;
@@ -570,7 +612,7 @@ Error LTO::addRegularLTO(BitcodeModule BM,
if (Sym.isCommon()) {
// FIXME: We should figure out what to do about commons defined by asm.
// For now they aren't reported correctly by ModuleSymbolTable.
- auto &CommonRes = RegularLTO.Commons[Sym.getIRName()];
+ auto &CommonRes = RegularLTO.Commons[Sym.getGV()->getName()];
CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
CommonRes.Prevailing |= Res.Prevailing;
@@ -578,7 +620,6 @@ Error LTO::addRegularLTO(BitcodeModule BM,
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
- assert(MsymI == MsymE);
return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
[](GlobalValue &, IRMover::ValueAdder) {},
@@ -586,10 +627,15 @@ Error LTO::addRegularLTO(BitcodeModule BM,
}
// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
+// FIXME: This function should not need to take as many parameters once we have
+// a bitcode symbol table.
+Error LTO::addThinLTO(BitcodeModule BM, Module &M,
+ iterator_range<InputFile::symbol_iterator> Syms,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
+
Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr = BM.getSummary();
if (!SummaryOrErr)
return SummaryOrErr.takeError();
@@ -599,15 +645,11 @@ Error LTO::addThinLTO(BitcodeModule BM,
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1);
+ addSymbolToGlobalRes(Used, Sym, Res, ThinLTO.ModuleMap.size() + 1);
- if (Res.Prevailing) {
- if (!Sym.getIRName().empty()) {
- auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
- Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
- ThinLTO.PrevailingModuleForGUID[GUID] = BM.getModuleIdentifier();
- }
- }
+ if (Res.Prevailing && Sym.isGV())
+ ThinLTO.PrevailingModuleForGUID[Sym.getGV()->getGUID()] =
+ BM.getModuleIdentifier();
}
if (!ThinLTO.ModuleMap.insert({BM.getModuleIdentifier(), BM}).second)
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 2007f560c16..b895c3fcc05 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -8,7 +8,6 @@ add_llvm_library(LLVMObject
ELFObjectFile.cpp
Error.cpp
IRObjectFile.cpp
- IRSymtab.cpp
MachOObjectFile.cpp
MachOUniversal.cpp
ModuleSummaryIndexObjectFile.cpp
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
deleted file mode 100644
index c69d7f9290f..00000000000
--- a/llvm/lib/Object/IRSymtab.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-//===- IRSymtab.cpp - implementation of IR symbol tables --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Object/IRSymtab.h"
-#include "llvm/CodeGen/Analysis.h"
-#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
-#include "llvm/IR/Module.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Object/ModuleSymbolTable.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/StringSaver.h"
-
-using namespace llvm;
-using namespace irsymtab;
-
-namespace {
-
-/// Stores the temporary state that is required to build an IR symbol table.
-struct Builder {
- SmallVector<char, 0> &Symtab;
- SmallVector<char, 0> &Strtab;
- Builder(SmallVector<char, 0> &Symtab, SmallVector<char, 0> &Strtab)
- : Symtab(Symtab), Strtab(Strtab) {}
-
- StringTableBuilder StrtabBuilder{StringTableBuilder::ELF};
-
- BumpPtrAllocator Alloc;
- StringSaver Saver{Alloc};
-
- DenseMap<const Comdat *, unsigned> ComdatMap;
- ModuleSymbolTable Msymtab;
- SmallPtrSet<GlobalValue *, 8> Used;
- Mangler Mang;
- Triple TT;
-
- std::vector<storage::Comdat> Comdats;
- std::vector<storage::Module> Mods;
- std::vector<storage::Symbol> Syms;
- std::vector<storage::Uncommon> Uncommons;
-
- std::string COFFLinkerOpts;
- raw_string_ostream COFFLinkerOptsOS{COFFLinkerOpts};
-
- void setStr(storage::Str &S, StringRef Value) {
- S.Offset = StrtabBuilder.add(Value);
- }
- template <typename T>
- void writeRange(storage::Range<T> &R, const std::vector<T> &Objs) {
- R.Offset = Symtab.size();
- R.Size = Objs.size();
- Symtab.insert(Symtab.end(), reinterpret_cast<const char *>(Objs.data()),
- reinterpret_cast<const char *>(Objs.data() + Objs.size()));
- }
-
- Error addModule(Module *M);
- Error addSymbol(ModuleSymbolTable::Symbol Sym);
-
- Error build(ArrayRef<Module *> Mods);
-};
-
-Error Builder::addModule(Module *M) {
- collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false);
-
- storage::Module Mod;
- Mod.Begin = Msymtab.symbols().size();
- Msymtab.addModule(M);
- Mod.End = Msymtab.symbols().size();
- Mods.push_back(Mod);
-
- if (TT.isOSBinFormatCOFF()) {
- if (auto E = M->materializeMetadata())
- return E;
- if (Metadata *Val = M->getModuleFlag("Linker Options")) {
- MDNode *LinkerOptions = cast<MDNode>(Val);
- for (const MDOperand &MDOptions : LinkerOptions->operands())
- for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
- COFFLinkerOptsOS << " " << cast<MDString>(MDOption)->getString();
- }
- }
-
- return Error::success();
-}
-
-Error Builder::addSymbol(ModuleSymbolTable::Symbol Msym) {
- Syms.emplace_back();
- storage::Symbol &Sym = Syms.back();
- Sym = {};
-
- Sym.UncommonIndex = -1;
- storage::Uncommon *Unc = nullptr;
- auto Uncommon = [&]() -> storage::Uncommon & {
- if (Unc)
- return *Unc;
- Sym.UncommonIndex = Uncommons.size();
- Uncommons.emplace_back();
- Unc = &Uncommons.back();
- *Unc = {};
- setStr(Unc->COFFWeakExternFallbackName, "");
- return *Unc;
- };
-
- SmallString<64> Name;
- {
- raw_svector_ostream OS(Name);
- Msymtab.printSymbolName(OS, Msym);
- }
- setStr(Sym.Name, Saver.save(StringRef(Name)));
-
- auto Flags = Msymtab.getSymbolFlags(Msym);
- if (Flags & object::BasicSymbolRef::SF_Undefined)
- Sym.Flags |= 1 << storage::Symbol::FB_undefined;
- if (Flags & object::BasicSymbolRef::SF_Weak)
- Sym.Flags |= 1 << storage::Symbol::FB_weak;
- if (Flags & object::BasicSymbolRef::SF_Common)
- Sym.Flags |= 1 << storage::Symbol::FB_common;
- if (Flags & object::BasicSymbolRef::SF_Indirect)
- Sym.Flags |= 1 << storage::Symbol::FB_indirect;
- if (Flags & object::BasicSymbolRef::SF_Global)
- Sym.Flags |= 1 << storage::Symbol::FB_global;
- if (Flags & object::BasicSymbolRef::SF_FormatSpecific)
- Sym.Flags |= 1 << storage::Symbol::FB_format_specific;
-
- Sym.ComdatIndex = -1;
- auto *GV = Msym.dyn_cast<GlobalValue *>();
- if (!GV) {
- setStr(Sym.IRName, "");
- return Error::success();
- }
-
- setStr(Sym.IRName, GV->getName());
-
- if (Used.count(GV))
- Sym.Flags |= 1 << storage::Symbol::FB_used;
- if (GV->isThreadLocal())
- Sym.Flags |= 1 << storage::Symbol::FB_tls;
- if (GV->hasGlobalUnnamedAddr())
- Sym.Flags |= 1 << storage::Symbol::FB_unnamed_addr;
- if (canBeOmittedFromSymbolTable(GV))
- Sym.Flags |= 1 << storage::Symbol::FB_may_omit;
- Sym.Flags |= unsigned(GV->getVisibility()) << storage::Symbol::FB_visibility;
-
- if (Flags & object::BasicSymbolRef::SF_Common) {
- Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize(
- GV->getType()->getElementType());
- Uncommon().CommonAlign = GV->getAlignment();
- }
-
- const GlobalObject *Base = GV->getBaseObject();
- if (!Base)
- return make_error<StringError>("Unable to determine comdat of alias!",
- inconvertibleErrorCode());
- if (const Comdat *C = Base->getComdat()) {
- auto P = ComdatMap.insert(std::make_pair(C, Comdats.size()));
- Sym.ComdatIndex = P.first->second;
-
- if (P.second) {
- storage::Comdat Comdat;
- setStr(Comdat.Name, C->getName());
- Comdats.push_back(Comdat);
- }
- }
-
- if (TT.isOSBinFormatCOFF()) {
- emitLinkerFlagsForGlobalCOFF(COFFLinkerOptsOS, GV, TT, Mang);
-
- if ((Flags & object::BasicSymbolRef::SF_Weak) &&
- (Flags & object::BasicSymbolRef::SF_Indirect)) {
- std::string FallbackName;
- raw_string_ostream OS(FallbackName);
- Msymtab.printSymbolName(
- OS, cast<GlobalValue>(
- cast<GlobalAlias>(GV)->getAliasee()->stripPointerCasts()));
- OS.flush();
- setStr(Uncommon().COFFWeakExternFallbackName, Saver.save(FallbackName));
- }
- }
-
- return Error::success();
-}
-
-Error Builder::build(ArrayRef<Module *> IRMods) {
- storage::Header Hdr;
-
- assert(!IRMods.empty());
- setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName());
- TT = Triple(IRMods[0]->getTargetTriple());
-
- // This adds the symbols for each module to Msymtab.
- for (auto *M : IRMods)
- if (Error Err = addModule(M))
- return Err;
-
- for (ModuleSymbolTable::Symbol Msym : Msymtab.symbols())
- if (Error Err = addSymbol(Msym))
- return Err;
-
- COFFLinkerOptsOS.flush();
- setStr(Hdr.COFFLinkerOpts, COFFLinkerOpts);
-
- // We are about to fill in the header's range fields, so reserve space for it
- // and copy it in afterwards.
- Symtab.resize(sizeof(storage::Header));
- writeRange(Hdr.Modules, Mods);
- writeRange(Hdr.Comdats, Comdats);
- writeRange(Hdr.Symbols, Syms);
- writeRange(Hdr.Uncommons, Uncommons);
-
- *reinterpret_cast<storage::Header *>(Symtab.data()) = Hdr;
-
- raw_svector_ostream OS(Strtab);
- StrtabBuilder.finalizeInOrder();
- StrtabBuilder.write(OS);
-
- return Error::success();
-}
-
-} // anonymous namespace
-
-Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
- SmallVector<char, 0> &Strtab) {
- return Builder(Symtab, Strtab).build(Mods);
-}
OpenPOWER on IntegriCloud