From 0a7a2ef6b52b1d28934d121b59ec36ae899708c4 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 3 Jul 2014 18:59:23 +0000 Subject: [PATCH] Add support for inline asm symbols to IRObjectFile. This also enables it in llvm-nm so that it can be tested. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212282 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/IRObjectFile.h | 3 +- include/llvm/Object/RecordStreamer.h | 42 ++++++++ lib/LTO/LTOModule.cpp | 101 +----------------- lib/Object/CMakeLists.txt | 1 + lib/Object/IRObjectFile.cpp | 151 +++++++++++++++++++++++---- lib/Object/LLVMBuild.txt | 2 +- lib/Object/RecordStreamer.cpp | 100 ++++++++++++++++++ test/Object/nm-ir.ll | 11 ++ tools/llvm-nm/CMakeLists.txt | 1 + tools/llvm-nm/llvm-nm.cpp | 15 ++- 10 files changed, 300 insertions(+), 127 deletions(-) create mode 100644 include/llvm/Object/RecordStreamer.h create mode 100644 lib/Object/RecordStreamer.cpp diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 3e6817554ee..2ce9c95d084 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -25,6 +25,7 @@ namespace object { class IRObjectFile : public SymbolicFile { std::unique_ptr M; std::unique_ptr Mang; + std::vector> AsmSymbols; public: IRObjectFile(std::unique_ptr Object, std::error_code &EC, @@ -34,7 +35,7 @@ public: std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue &getSymbolGV(DataRefImpl Symb) const; + const GlobalValue *getSymbolGV(DataRefImpl Symb) const; basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; diff --git a/include/llvm/Object/RecordStreamer.h b/include/llvm/Object/RecordStreamer.h new file mode 100644 index 00000000000..10e70ef16e2 --- /dev/null +++ b/include/llvm/Object/RecordStreamer.h @@ -0,0 +1,42 @@ +//===-- RecordStreamer.h - Record asm defined and used symbols ---*- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RECORD_STREAMER +#define LLVM_OBJECT_RECORD_STREAMER + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class RecordStreamer : public MCStreamer { +public: + enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; + +private: + StringMap Symbols; + void markDefined(const MCSymbol &Symbol); + void markGlobal(const MCSymbol &Symbol); + void markUsed(const MCSymbol &Symbol); + void visitUsedSymbol(const MCSymbol &Sym) override; + +public: + typedef StringMap::const_iterator const_iterator; + const_iterator begin(); + const_iterator end(); + RecordStreamer(MCContext &Context); + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; +}; +} +#endif diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index 6c1fadab845..769f97a10a2 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -24,11 +24,11 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/RecordStreamer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -552,105 +552,6 @@ LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { entry.setValue(info); } -namespace { - - class RecordStreamer : public MCStreamer { - public: - enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; - - private: - StringMap Symbols; - - void markDefined(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Global: - S = DefinedGlobal; - break; - case NeverSeen: - case Defined: - case Used: - S = Defined; - break; - } - } - void markGlobal(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Defined: - S = DefinedGlobal; - break; - - case NeverSeen: - case Global: - case Used: - S = Global; - break; - } - } - void markUsed(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Defined: - case Global: - break; - - case NeverSeen: - case Used: - S = Used; - break; - } - } - - void visitUsedSymbol(const MCSymbol &Sym) override { - markUsed(Sym); - } - - public: - typedef StringMap::const_iterator const_iterator; - - const_iterator begin() { - return Symbols.begin(); - } - - const_iterator end() { - return Symbols.end(); - } - - RecordStreamer(MCContext &Context) : MCStreamer(Context) {} - - void EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) override { - MCStreamer::EmitInstruction(Inst, STI); - } - void EmitLabel(MCSymbol *Symbol) override { - MCStreamer::EmitLabel(Symbol); - markDefined(*Symbol); - } - void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override { - markDefined(*Symbol); - MCStreamer::EmitAssignment(Symbol, Value); - } - bool EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) override { - if (Attribute == MCSA_Global) - markGlobal(*Symbol); - return true; - } - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size , unsigned ByteAlignment) override { - markDefined(*Symbol); - } - void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override { - markDefined(*Symbol); - } - }; -} // end anonymous namespace - /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the /// defined or undefined lists. bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 00bf1e30c21..5b08e42dd9e 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -12,5 +12,6 @@ add_llvm_library(LLVMObject MachOUniversal.cpp Object.cpp ObjectFile.cpp + RecordStreamer.cpp SymbolicFile.cpp ) diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp index f20ce6cf665..27b6d208b97 100644 --- a/lib/Object/IRObjectFile.cpp +++ b/lib/Object/IRObjectFile.cpp @@ -17,7 +17,17 @@ #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/RecordStreamer.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace object; @@ -37,12 +47,85 @@ IRObjectFile::IRObjectFile(std::unique_ptr Object, return; Mang.reset(new Mangler(DL)); + + const std::string &InlineAsm = M->getModuleInlineAsm(); + if (InlineAsm.empty()) + return; + + StringRef Triple = M->getTargetTriple(); + std::string Err; + const Target *T = TargetRegistry::lookupTarget(Triple, Err); + if (!T) + return; + + std::unique_ptr MRI(T->createMCRegInfo(Triple)); + if (!MRI) + return; + + std::unique_ptr MAI(T->createMCAsmInfo(*MRI, Triple)); + if (!MAI) + return; + + std::unique_ptr STI( + T->createMCSubtargetInfo(Triple, "", "")); + if (!STI) + return; + + std::unique_ptr MCII(T->createMCInstrInfo()); + if (!MCII) + return; + + MCObjectFileInfo MOFI; + MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); + MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); + std::unique_ptr Streamer(new RecordStreamer(MCCtx)); + + std::unique_ptr Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); + SourceMgr SrcMgr; + SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); + std::unique_ptr Parser( + createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); + + MCTargetOptions MCOptions; + std::unique_ptr TAP( + T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); + if (!TAP) + return; + + Parser->setTargetParser(*TAP); + if (Parser->Run(false)) + return; + + for (auto &KV : *Streamer) { + StringRef Key = KV.first(); + RecordStreamer::State Value = KV.second; + uint32_t Res = BasicSymbolRef::SF_None; + switch (Value) { + case RecordStreamer::NeverSeen: + llvm_unreachable("foo"); + case RecordStreamer::DefinedGlobal: + Res |= BasicSymbolRef::SF_Global; + break; + case RecordStreamer::Defined: + break; + case RecordStreamer::Global: + case RecordStreamer::Used: + Res |= BasicSymbolRef::SF_Undefined; + Res |= BasicSymbolRef::SF_Global; + break; + } + AsmSymbols.push_back( + std::make_pair(Key, std::move(Res))); + } } IRObjectFile::~IRObjectFile() { M->getMaterializer()->releaseBuffer(); } -static const GlobalValue &getGV(DataRefImpl &Symb) { - return *reinterpret_cast(Symb.p & ~uintptr_t(3)); +static const GlobalValue *getGV(DataRefImpl &Symb) { + if ((Symb.p & 3) == 3) + return nullptr; + + return reinterpret_cast(Symb.p & ~uintptr_t(3)); } static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { @@ -66,31 +149,43 @@ static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { return reinterpret_cast(GV) | 0; } +static unsigned getAsmSymIndex(DataRefImpl Symb) { + assert((Symb.p & uintptr_t(3)) == 3); + uintptr_t Index = Symb.p & ~uintptr_t(3); + Index >>= 2; + return Index; +} + void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - const GlobalValue *GV = &getGV(Symb); - const Module &M = *GV->getParent(); + const GlobalValue *GV = getGV(Symb); uintptr_t Res; + switch (Symb.p & 3) { case 0: { Module::const_iterator Iter(static_cast(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); break; } case 1: { Module::const_global_iterator Iter(static_cast(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); break; } case 2: { Module::const_alias_iterator Iter(static_cast(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); + break; + } + case 3: { + unsigned Index = getAsmSymIndex(Symb); + assert(Index < AsmSymbols.size()); + ++Index; + Res = (Index << 2) | 3; break; } - case 3: - llvm_unreachable("Invalid symbol reference"); } Symb.p = Res; @@ -98,12 +193,18 @@ void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { - const GlobalValue &GV = getGV(Symb); + const GlobalValue *GV = getGV(Symb); + if (!GV) { + unsigned Index = getAsmSymIndex(Symb); + assert(Index <= AsmSymbols.size()); + OS << AsmSymbols[Index].first; + return object_error::success;; + } if (Mang) - Mang->getNameWithPrefix(OS, &GV, false); + Mang->getNameWithPrefix(OS, GV, false); else - OS << GV.getName(); + OS << GV->getName(); return object_error::success; } @@ -119,25 +220,31 @@ static bool isDeclaration(const GlobalValue &V) { } uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { - const GlobalValue &GV = getGV(Symb); + const GlobalValue *GV = getGV(Symb); + + if (!GV) { + unsigned Index = getAsmSymIndex(Symb); + assert(Index <= AsmSymbols.size()); + return AsmSymbols[Index].second; + } uint32_t Res = BasicSymbolRef::SF_None; - if (isDeclaration(GV)) + if (isDeclaration(*GV)) Res |= BasicSymbolRef::SF_Undefined; - if (GV.hasPrivateLinkage()) + if (GV->hasPrivateLinkage()) Res |= BasicSymbolRef::SF_FormatSpecific; - if (!GV.hasLocalLinkage()) + if (!GV->hasLocalLinkage()) Res |= BasicSymbolRef::SF_Global; - if (GV.hasCommonLinkage()) + if (GV->hasCommonLinkage()) Res |= BasicSymbolRef::SF_Common; - if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage()) + if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) Res |= BasicSymbolRef::SF_Weak; return Res; } -const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const { - const GlobalValue &GV = getGV(Symb); +const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { + const GlobalValue *GV = getGV(Symb); return GV; } @@ -150,7 +257,9 @@ basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { basic_symbol_iterator IRObjectFile::symbol_end_impl() const { DataRefImpl Ret; - Ret.p = 3; + uint64_t NumAsm = AsmSymbols.size(); + NumAsm <<= 2; + Ret.p = 3 | NumAsm; return basic_symbol_iterator(BasicSymbolRef(Ret, this)); } diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt index d64ac8722f5..8acacba78dd 100644 --- a/lib/Object/LLVMBuild.txt +++ b/lib/Object/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Object parent = Libraries -required_libraries = BitReader Core Support MC +required_libraries = BitReader Core Support MC MCParser diff --git a/lib/Object/RecordStreamer.cpp b/lib/Object/RecordStreamer.cpp new file mode 100644 index 00000000000..c158c0fb35d --- /dev/null +++ b/lib/Object/RecordStreamer.cpp @@ -0,0 +1,100 @@ +//===-- RecordStreamer.cpp - Record asm definde and used symbols ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/RecordStreamer.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +void RecordStreamer::markDefined(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Global: + S = DefinedGlobal; + break; + case NeverSeen: + case Defined: + case Used: + S = Defined; + break; + } +} + +void RecordStreamer::markGlobal(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + S = DefinedGlobal; + break; + + case NeverSeen: + case Global: + case Used: + S = Global; + break; + } +} + +void RecordStreamer::markUsed(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + case Global: + break; + + case NeverSeen: + case Used: + S = Used; + break; + } +} + +void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } + +RecordStreamer::const_iterator RecordStreamer::begin() { + return Symbols.begin(); +} + +RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } + +RecordStreamer::RecordStreamer(MCContext &Context) : MCStreamer(Context) {} + +void RecordStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCStreamer::EmitInstruction(Inst, STI); +} + +void RecordStreamer::EmitLabel(MCSymbol *Symbol) { + MCStreamer::EmitLabel(Symbol); + markDefined(*Symbol); +} + +void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + markDefined(*Symbol); + MCStreamer::EmitAssignment(Symbol, Value); +} + +bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + if (Attribute == MCSA_Global) + markGlobal(*Symbol); + return true; +} + +void RecordStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + markDefined(*Symbol); +} + +void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + markDefined(*Symbol); +} diff --git a/test/Object/nm-ir.ll b/test/Object/nm-ir.ll index ddf4125e39c..6bb7e2323a2 100644 --- a/test/Object/nm-ir.ll +++ b/test/Object/nm-ir.ll @@ -10,6 +10,17 @@ ; CHECK-NEXT: d g2 ; CHECK-NEXT: C g3 ; CHECK-NOT: g4 +; CHECK-NEXT: T global_asm_sym +; CHECK-NEXT: t local_asm_sym +; CHECK-NEXT: U undef_asm_sy + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +module asm ".global global_asm_sym" +module asm "global_asm_sym:" +module asm "local_asm_sym:" +module asm ".long undef_asm_sym" @g1 = global i32 42 @g2 = internal global i32 42 diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt index 6128bf9adf7..1fe4a2dbaca 100644 --- a/tools/llvm-nm/CMakeLists.txt +++ b/tools/llvm-nm/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} Object Support ) diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 0264b708ad6..3f9ce24471a 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -37,6 +37,7 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TargetSelect.h" #include #include #include @@ -637,8 +638,10 @@ static char getSymbolNMTypeChar(const GlobalValue &GV) { } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { - const GlobalValue &GV = Obj.getSymbolGV(I->getRawDataRefImpl()); - return getSymbolNMTypeChar(GV); + const GlobalValue *GV = Obj.getSymbolGV(I->getRawDataRefImpl()); + if (!GV) + return 't'; + return getSymbolNMTypeChar(*GV); } template @@ -723,8 +726,8 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) { continue; if (WithoutAliases) { if (IRObjectFile *IR = dyn_cast(Obj)) { - const GlobalValue &GV = IR->getSymbolGV(I->getRawDataRefImpl()); - if (isa(GV)) + const GlobalValue *GV = IR->getSymbolGV(I->getRawDataRefImpl()); + if (GV && isa(GV)) continue; } } @@ -993,6 +996,10 @@ int main(int argc, char **argv) { if (error(sys::ChangeStdinToBinary())) return 1; + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + ToolName = argv[0]; if (BSDFormat) OutputFormat = bsd;