From 1f3f774f104998f715783967ee852f4682f87fa8 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 6 Feb 2019 02:35:18 +0000 Subject: [PATCH] [WebAssembly] Implement --trace and --trace-symbol Differential Revision: https://reviews.llvm.org/D57725 llvm-svn: 353264 --- lld/test/wasm/trace-symbol.ll | 23 ++++++++++++++++ lld/test/wasm/trace.test | 8 ++++++ lld/wasm/Config.h | 1 + lld/wasm/Driver.cpp | 5 ++++ lld/wasm/Options.td | 6 +++++ lld/wasm/SymbolTable.cpp | 51 +++++++++++++++++++++++++++-------- lld/wasm/SymbolTable.h | 9 ++++++- lld/wasm/Symbols.cpp | 13 +++++++++ lld/wasm/Symbols.h | 17 ++++++++++-- 9 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 lld/test/wasm/trace-symbol.ll create mode 100644 lld/test/wasm/trace.test diff --git a/lld/test/wasm/trace-symbol.ll b/lld/test/wasm/trace-symbol.ll new file mode 100644 index 000000000000..649b425f4152 --- /dev/null +++ b/lld/test/wasm/trace-symbol.ll @@ -0,0 +1,23 @@ +; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o +; RUN: llc -filetype=obj -o %t.o %s +; RUN: wasm-ld -o %t.wasm %t.o %t.ret32.o -y ret32 -y _start 2>&1 | FileCheck %s -check-prefix=BOTH + +; check alias +; RUN: wasm-ld -o %t.wasm %t.o %t.ret32.o -trace-symbol=_start 2>&1 | FileCheck %s -check-prefixes=JUST-START + +target triple = "wasm32-unknown-unknown" + +declare i32 @ret32(float %arg) + +define void @_start() { +entry: + %call1 = call i32 @ret32(float 0.0) + ret void +} + +; BOTH: .o: definition of _start +; BOTH: .o: reference to ret32 +; BOTH: .ret32.o: definition of ret32 + +; JUST-START: .o: definition of _start +; JUST-START-NOT: ret32 diff --git a/lld/test/wasm/trace.test b/lld/test/wasm/trace.test new file mode 100644 index 000000000000..bf74bd498066 --- /dev/null +++ b/lld/test/wasm/trace.test @@ -0,0 +1,8 @@ +RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.foo.o + +# Check -t +RUN: wasm-ld %t.foo.o -o out.wasm -t 2>&1 | FileCheck %s +CHECK: {{.*}}.foo.o + +# Check --trace alias +RUN: wasm-ld %t.foo.o -o out.wasm --trace 2>&1 | FileCheck %s diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h index 3897ef65b8d7..c5f22eb537dd 100644 --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -38,6 +38,7 @@ struct Configuration { bool StripAll; bool StripDebug; bool StackFirst; + bool Trace; uint32_t GlobalBase; uint32_t InitialMemory; uint32_t MaxMemory; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 860d9f5fe65e..396f30af5846 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -371,6 +371,7 @@ static void setConfigs(opt::InputArgList &Args) { Config->StripAll = Args.hasArg(OPT_strip_all); Config->StripDebug = Args.hasArg(OPT_strip_debug); Config->StackFirst = Args.hasArg(OPT_stack_first); + Config->Trace = Args.hasArg(OPT_trace); Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); Config->ThinLTOCachePolicy = CHECK( parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), @@ -556,6 +557,10 @@ void LinkerDriver::link(ArrayRef ArgsArr) { Config->AllowUndefined = true; } + // Handle --trace-symbol. + for (auto *Arg : Args.filtered(OPT_trace_symbol)) + Symtab->trace(Arg->getValue()); + if (!Config->Relocatable) createSyntheticSymbols(); diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td index 3ed55b4bcda0..591d624e666d 100644 --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -93,6 +93,10 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; +def trace: F<"trace">, HelpText<"Print the names of the input files">; + +defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">; + defm undefined: Eq<"undefined", "Force undefined symbol during linking">; def v: Flag<["-"], "v">, HelpText<"Display the version number">; @@ -160,6 +164,8 @@ def: Flag<["-"], "m">, Alias; def: Flag<["-"], "r">, Alias; def: Flag<["-"], "s">, Alias, HelpText<"Alias for --strip-all">; def: Flag<["-"], "S">, Alias, HelpText<"Alias for --strip-debug">; +def: Flag<["-"], "t">, Alias, HelpText<"Alias for --trace">; +def: JoinedOrSeparate<["-"], "y">, Alias, HelpText<"Alias for --trace-symbol">; def: JoinedOrSeparate<["-"], "u">, Alias; // LTO-related options. diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index e45dc6bec715..79e85d5bc9ea 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -28,6 +28,8 @@ SymbolTable *lld::wasm::Symtab; void SymbolTable::addFile(InputFile *File) { log("Processing: " + toString(File)); + if (Config->Trace) + message(toString(File)); File->parse(); // LLVM bitcode file @@ -73,21 +75,42 @@ void SymbolTable::reportRemainingUndefines() { } Symbol *SymbolTable::find(StringRef Name) { - return SymMap.lookup(CachedHashStringRef(Name)); + auto It = SymMap.find(CachedHashStringRef(Name)); + if (It == SymMap.end() || It->second == -1) + return nullptr; + return SymVector[It->second]; +} + +std::pair SymbolTable::insertName(StringRef Name) { + bool Trace = false; + auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); + int &SymIndex = P.first->second; + bool IsNew = P.second; + if (SymIndex == -1) { + SymIndex = SymVector.size(); + Trace = true; + IsNew = true; + } + + if (!IsNew) + return {SymVector[SymIndex], false}; + + Symbol *Sym = reinterpret_cast(make()); + Sym->IsUsedInRegularObj = false; + Sym->Traced = Trace; + SymVector.emplace_back(Sym); + return {Sym, true}; } std::pair SymbolTable::insert(StringRef Name, InputFile *File) { - bool Inserted = false; - Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; - if (!Sym) { - Sym = reinterpret_cast(make()); - Sym->IsUsedInRegularObj = false; - SymVector.emplace_back(Sym); - Inserted = true; - } + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insertName(Name); + if (!File || File->kind() == InputFile::ObjectKind) - Sym->IsUsedInRegularObj = true; - return {Sym, Inserted}; + S->IsUsedInRegularObj = true; + + return {S, WasInserted}; } static void reportTypeError(const Symbol *Existing, const InputFile *File, @@ -409,3 +432,9 @@ void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { bool SymbolTable::addComdat(StringRef Name) { return Comdats.insert(CachedHashStringRef(Name)).second; } + +// Set a flag for --trace-symbol so that we can print out a log message +// if a new symbol with the same name is inserted into the symbol table. +void SymbolTable::trace(StringRef Name) { + SymMap.insert({CachedHashStringRef(Name), -1}); +} diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h index f0bdd6cc01c8..ed5c0ca77dd6 100644 --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -46,8 +46,11 @@ public: void reportRemainingUndefines(); ArrayRef getSymbols() const { return SymVector; } + Symbol *find(StringRef Name); + void trace(StringRef Name); + Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, InputFunction *Function); Symbol *addDefinedData(StringRef Name, uint32_t Flags, InputFile *File, @@ -76,8 +79,12 @@ public: private: std::pair insert(StringRef Name, InputFile *File); + std::pair insertName(StringRef Name); - llvm::DenseMap SymMap; + // Maps symbol names to index into the SymVector. -1 means that symbols + // is to not yet in the vector but it should have tracing enabled if it is + // ever added. + llvm::DenseMap SymMap; std::vector SymVector; llvm::DenseSet Comdats; diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index 0c3c0e06576c..4721e35f9f86 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -293,3 +293,16 @@ std::string lld::toString(wasm::Symbol::Kind Kind) { } llvm_unreachable("invalid symbol kind"); } + +// Print out a log message for --trace-symbol. +void lld::wasm::printTraceSymbol(Symbol *Sym) { + std::string S; + if (Sym->isUndefined()) + S = ": reference to "; + else if (Sym->isLazy()) + S = ": lazy definition of "; + else + S = ": definition of "; + + message(toString(Sym->getFile()) + S + Sym->getName()); +} diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 652d0a9ef6a3..535948cc0aac 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -100,10 +100,14 @@ public: unsigned IsUsedInRegularObj : 1; unsigned ForceExport : 1; + // True if this symbol is specified by --trace-symbol option. + unsigned Traced : 1; + protected: Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F) - : IsUsedInRegularObj(false), ForceExport(false), Name(Name), - SymbolKind(K), Flags(Flags), File(F), Referenced(!Config->GcSections) {} + : IsUsedInRegularObj(false), ForceExport(false), Traced(false), + Name(Name), SymbolKind(K), Flags(Flags), File(F), + Referenced(!Config->GcSections) {} StringRef Name; Kind SymbolKind; @@ -402,6 +406,8 @@ union SymbolUnion { alignas(SectionSymbol) char I[sizeof(SectionSymbol)]; }; +void printTraceSymbol(Symbol *Sym); + template T *replaceSymbol(Symbol *S, ArgT &&... Arg) { static_assert(std::is_trivially_destructible(), @@ -417,6 +423,13 @@ T *replaceSymbol(Symbol *S, ArgT &&... Arg) { T *S2 = new (S) T(std::forward(Arg)...); S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj; S2->ForceExport = SymCopy.ForceExport; + S2->Traced = SymCopy.Traced; + + // Print out a log message if --trace-symbol was specified. + // This is for debugging. + if (S2->Traced) + printTraceSymbol(S2); + return S2; }