Index: lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -50,7 +50,8 @@ /// /// In detail, this pass does following things: /// -/// 1) Create three global variables: __THREW__, __threwValue, and __tempRet0. +/// 1) Assumes the existence of global variables: __THREW__, __threwValue, and +/// __tempRet0. /// __tempRet0 will be set within __cxa_find_matching_catch() function in /// JS library, and __THREW__ and __threwValue will be set in invoke wrappers /// in JS glue code. For what invoke wrappers are, refer to 3). These @@ -65,9 +66,10 @@ /// /// * Exception handling /// -/// 2) Create setThrew and setTempRet0 functions. -/// The global variables created in 1) will exist in wasm address space, -/// but their values should be set in JS code, so we provide these functions +/// 2) We assume the existence of setThrew and setTempRet0 functions at link +/// time. +/// The global variables in 1) will exist in wasm address space, +/// but their values should be set in JS code, so these functions /// as interfaces to JS glue code. These functions are equivalent to the /// following JS functions, which actually exist in asm.js version of JS /// library. @@ -225,13 +227,8 @@ namespace { class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass { - static const char *ThrewGVName; - static const char *ThrewValueGVName; - static const char *TempRet0GVName; static const char *ResumeFName; static const char *EHTypeIDFName; - static const char *SetThrewFName; - static const char *SetTempRet0FName; static const char *EmLongjmpFName; static const char *EmLongjmpJmpbufFName; static const char *SaveSetjmpFName; @@ -277,9 +274,6 @@ bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); } bool canLongjmp(Module &M, const Value *Callee) const; - void createSetThrewFunction(Module &M); - void createSetTempRet0Function(Module &M); - void rebuildSSA(Function &F); public: @@ -300,14 +294,9 @@ }; } // End anonymous namespace -const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewGVName = "__THREW__"; -const char *WebAssemblyLowerEmscriptenEHSjLj::ThrewValueGVName = "__threwValue"; -const char *WebAssemblyLowerEmscriptenEHSjLj::TempRet0GVName = "__tempRet0"; const char *WebAssemblyLowerEmscriptenEHSjLj::ResumeFName = "__resumeException"; const char *WebAssemblyLowerEmscriptenEHSjLj::EHTypeIDFName = "llvm_eh_typeid_for"; -const char *WebAssemblyLowerEmscriptenEHSjLj::SetThrewFName = "setThrew"; -const char *WebAssemblyLowerEmscriptenEHSjLj::SetTempRet0FName = "setTempRet0"; const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpFName = "emscripten_longjmp"; const char *WebAssemblyLowerEmscriptenEHSjLj::EmLongjmpJmpbufFName = @@ -343,15 +332,15 @@ return true; } -// Returns an available name for a global value. -// If the proposed name already exists in the module, adds '_' at the end of -// the name until the name is available. -static inline std::string createGlobalValueName(const Module &M, - const std::string &Propose) { - std::string Name = Propose; - while (M.getNamedGlobal(Name)) - Name += "_"; - return Name; +// Get a global variable with the given name. If it doesn't exist declare it, +// which will generate an import and asssumes that it will exist at link time. +static GlobalVariable *getGlobalVariable(Module &M, Type *Ty, + const std::string &Name) { + GlobalVariable* V = M.getNamedGlobal(Name); + if (V) + return V; + return new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, nullptr, + Name); } // Simple function name mangler. @@ -492,9 +481,10 @@ bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M, const Value *Callee) const { - if (auto *CalleeF = dyn_cast(Callee)) + if (auto *CalleeF = dyn_cast(Callee)) { if (CalleeF->isIntrinsic()) return false; + } // The reason we include malloc/free here is to exclude the malloc/free // calls generated in setjmp prep / cleanup routines. @@ -602,64 +592,6 @@ LongjmpResult = IRB.CreateLoad(TempRet0GV, "longjmp_result"); } -// Create setThrew function -// function setThrew(threw, value) { -// if (__THREW__ == 0) { -// __THREW__ = threw; -// __threwValue = value; -// } -// } -void WebAssemblyLowerEmscriptenEHSjLj::createSetThrewFunction(Module &M) { - LLVMContext &C = M.getContext(); - IRBuilder<> IRB(C); - - assert(!M.getNamedGlobal(SetThrewFName) && "setThrew already exists"); - Type *Params[] = {IRB.getInt32Ty(), IRB.getInt32Ty()}; - FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false); - Function *F = - Function::Create(FTy, GlobalValue::ExternalLinkage, SetThrewFName, &M); - Argument *Arg1 = &*(F->arg_begin()); - Argument *Arg2 = &*std::next(F->arg_begin()); - Arg1->setName("threw"); - Arg2->setName("value"); - BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); - BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", F); - BasicBlock *EndBB = BasicBlock::Create(C, "if.end", F); - - IRB.SetInsertPoint(EntryBB); - Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val"); - Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(0), "cmp"); - IRB.CreateCondBr(Cmp, ThenBB, EndBB); - - IRB.SetInsertPoint(ThenBB); - IRB.CreateStore(Arg1, ThrewGV); - IRB.CreateStore(Arg2, ThrewValueGV); - IRB.CreateBr(EndBB); - - IRB.SetInsertPoint(EndBB); - IRB.CreateRetVoid(); -} - -// Create setTempRet0 function -// function setTempRet0(value) { -// __tempRet0 = value; -// } -void WebAssemblyLowerEmscriptenEHSjLj::createSetTempRet0Function(Module &M) { - LLVMContext &C = M.getContext(); - IRBuilder<> IRB(C); - - assert(!M.getNamedGlobal(SetTempRet0FName) && "setTempRet0 already exists"); - Type *Params[] = {IRB.getInt32Ty()}; - FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false); - Function *F = - Function::Create(FTy, GlobalValue::ExternalLinkage, SetTempRet0FName, &M); - F->arg_begin()->setName("value"); - BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); - IRB.SetInsertPoint(EntryBB); - IRB.CreateStore(&*F->arg_begin(), TempRet0GV); - IRB.CreateRetVoid(); -} - void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) { DominatorTree &DT = getAnalysis(F).getDomTree(); DT.recalculate(F); // CFG has been changed @@ -697,17 +629,12 @@ bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty(); bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed); - // Create global variables __THREW__, threwValue, and __tempRet0, which are - // used in common for both exception handling and setjmp/longjmp handling - ThrewGV = new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, ThrewGVName)); - ThrewValueGV = new GlobalVariable( - M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, ThrewValueGVName)); - TempRet0GV = new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::ExternalLinkage, IRB.getInt32(0), - createGlobalValueName(M, TempRet0GVName)); + // Declare (or get) global variables __THREW__, threwValue, and __tempRet0, + // which are used in common for both exception handling and setjmp/longjmp + // handling + ThrewGV = getGlobalVariable(M, IRB.getInt32Ty(), "__THREW__"); + ThrewValueGV = getGlobalVariable(M, IRB.getInt32Ty(), "__threwValue"); + TempRet0GV = getGlobalVariable(M, IRB.getInt32Ty(), "__tempRet0"); bool Changed = false; @@ -736,12 +663,6 @@ if (DoSjLj) { Changed = true; // We have setjmp or longjmp somewhere - Function *MallocF = M.getFunction("malloc"); - Function *FreeF = M.getFunction("free"); - if (!MallocF || !FreeF) - report_fatal_error( - "malloc and free must be linked into the module if setjmp is used"); - // Register saveSetjmp function FunctionType *SetjmpFTy = SetjmpF->getFunctionType(); SmallVector Params = {SetjmpFTy->getParamType(0), @@ -785,9 +706,6 @@ if (!Changed) { // Delete unused global variables and functions - ThrewGV->eraseFromParent(); - ThrewValueGV->eraseFromParent(); - TempRet0GV->eraseFromParent(); if (ResumeF) ResumeF->eraseFromParent(); if (EHTypeIDF) @@ -801,12 +719,6 @@ return false; } - // If we have made any changes while doing exception handling or - // setjmp/longjmp handling, we have to create these functions for JavaScript - // to call. - createSetThrewFunction(M); - createSetTempRet0Function(M); - return true; } Index: tools/llvm-dis/llvm-dis.cpp =================================================================== --- tools/llvm-dis/llvm-dis.cpp +++ tools/llvm-dis/llvm-dis.cpp @@ -150,15 +150,15 @@ int main(int argc, char **argv) { InitLLVM X(argc, argv); - ExitOnErr.setBanner(std::string(argv[0]) + ": error: "); - LLVMContext Context; Context.setDiagnosticHandler( llvm::make_unique(argv[0])); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); + ExitOnErr.setBanner(std::string(argv[0]) + ": " + InputFilename + ": error: "); std::unique_ptr MB = ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename))); + ExitOnErr.setBanner(std::string(argv[0]) + ": error: "); std::unique_ptr M = ExitOnErr(getLazyBitcodeModule( *MB, Context, /*ShouldLazyLoadMetadata=*/true, SetImporting)); if (MaterializeMetadata) Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -359,11 +359,8 @@ LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, llvm::Error E) { assert(E); - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(std::move(E), OS, ""); - OS.flush(); - errs() << ToolName << ": '" << File << "': " << Buf; + logAllUnhandledErrors(std::move(E), errs(), + ToolName + ": '" + File + "': "); exit(1); } @@ -372,18 +369,15 @@ llvm::Error E, StringRef ArchitectureName) { assert(E); - errs() << ToolName << ": "; + std::string Banner = ToolName.str() + ": "; if (ArchiveName != "") - errs() << ArchiveName << "(" << FileName << ")"; + Banner += ArchiveName.str() + "(" + FileName.str() + ")"; else - errs() << "'" << FileName << "'"; + Banner += "'" + FileName.str() + "'"; if (!ArchitectureName.empty()) - errs() << " (for architecture " << ArchitectureName << ")"; - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(std::move(E), OS, ""); - OS.flush(); - errs() << ": " << Buf; + Banner += " (for architecture " + ArchitectureName.str() + ")"; + Banner += ": "; + logAllUnhandledErrors(std::move(E), errs(), Banner); exit(1); }