diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -169,6 +169,9 @@ delete AddrLabelSymbols; AddrLabelSymbols = nullptr; + if (Context.hadError()) + TheModule->getContext().emitError("MC error"); + Context.reset(); // We don't clear the ExternalContext. diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -30,12 +30,16 @@ #include "llvm/LTO/LTOBackend.h" #include "llvm/LTO/SummaryBasedOptimizations.h" #include "llvm/Linker/IRMover.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/SHA1.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -700,6 +704,55 @@ GO->setComdat(nullptr); } +static const char *getTargetAsmSeparator(const Module &M) { + std::string Err; + const Triple TT(M.getTargetTriple()); + const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); + assert(T && T->hasMCAsmParser()); + + MCTargetOptions MCOptions; + MCRegisterInfo MRI; + std::unique_ptr MAI(T->createMCAsmInfo(MRI, TT.str(), MCOptions)); + if (!MAI) + return "\\n"; + return MAI->getSeparatorString(); +} + +static void handleModuleInlineAsm(Module &M, + std::set &NonPrevailingAsmSymbol) { + ModuleSymbolTable::CollectAsmSymvers(M, [&](StringRef Name, StringRef Alias) { + if (!NonPrevailingAsmSymbol.count(Alias)) + NonPrevailingAsmSymbol.erase(Name); + }); + + if (NonPrevailingAsmSymbol.empty()) + return; + + std::string IA = M.getModuleInlineAsm(); + std::string Sep = getTargetAsmSeparator(M); + std::string PrefixPat = "(^|[[:blank:]]+)"; + std::string SuffixPat = "($|" + Sep + ")"; + std::string Symbols = "(" + join(NonPrevailingAsmSymbol, "|") + ")"; + std::vector Pats = {// Remove assignment directive. + "\\.(set|equ|equiv|eqv)[[:blank:]]+" + + Symbols + "[[:blank:]]*,[^" + Sep + + "]+" + SuffixPat, + // Remove labels. + Symbols + ":", + // Remove symbols. + "\\.(weak|global|globl)[[:blank:]]+" + + Symbols + "[[:blank:]]*" + SuffixPat}; + for (auto P : Pats) { + Regex RE(PrefixPat + P, Regex::Newline); + assert(RE.isValid()); + IA = RE.sub("", IA); + } + + if (std::all_of(IA.begin(), IA.end(), [](auto c) { return std::isspace(c); })) + IA = ""; + M.setModuleInlineAsm(IA); +} + // Add a regular LTO object to the link. // The resulting module needs to be linked into the combined LTO module with // linkRegularLTO. @@ -752,6 +805,7 @@ Skip(); std::set NonPrevailingComdats; + std::set NonPrevailingAsmSymbol; for (const InputFile::Symbol &Sym : Syms) { assert(ResI != ResE); SymbolResolution Res = *ResI++; @@ -798,7 +852,13 @@ GV->setDLLStorageClass(GlobalValue::DLLStorageClassTypes:: DefaultStorageClass); } - } + } else if (auto *AS = Msym.dyn_cast()) { + // Collect non-prevailing symbols. + if (!Res.Prevailing) + NonPrevailingAsmSymbol.insert(AS->first); + } else + llvm_unreachable("unknown symbol type"); + // Common resolution: collect the maximum size/alignment over all commons. // We also record if we see an instance of a common as prevailing, so that // if none is prevailing we can ignore it later. @@ -812,11 +872,15 @@ CommonRes.Align = max(*SymAlign, CommonRes.Align); CommonRes.Prevailing |= Res.Prevailing; } - } + if (!M.getComdatSymbolTable().empty()) for (GlobalValue &GV : M.global_values()) handleNonPrevailingComdat(GV, NonPrevailingComdats); + + if (!NonPrevailingAsmSymbol.empty()) + handleModuleInlineAsm(M, NonPrevailingAsmSymbol); + assert(MsymI == MsymE); return std::move(Mod); } diff --git a/llvm/test/CodeGen/AMDGPU/lds-initializer.ll b/llvm/test/CodeGen/AMDGPU/lds-initializer.ll --- a/llvm/test/CodeGen/AMDGPU/lds-initializer.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-initializer.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s -; RUN: llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s ; CHECK: lds: unsupported initializer for address space diff --git a/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll b/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll --- a/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s -; RUN: llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s ; CHECK: lds: unsupported initializer for address space diff --git a/llvm/test/CodeGen/XCore/section-name.ll b/llvm/test/CodeGen/XCore/section-name.ll --- a/llvm/test/CodeGen/XCore/section-name.ll +++ b/llvm/test/CodeGen/XCore/section-name.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=xcore -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc < %s -march=xcore -o /dev/null 2>&1 | FileCheck %s @bar = internal global i32 zeroinitializer diff --git a/llvm/test/LTO/X86/weak-asm.ll b/llvm/test/LTO/X86/weak-asm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/weak-asm.ll @@ -0,0 +1,48 @@ +; RUN: split-file %s %t +; RUN: opt %t/t1.ll -o %t1 +; RUN: opt %t/t2.ll -o %t2 +; RUN: opt %t/t3.ll -o %t3 +; RUN: llvm-lto2 run -o %t4 -save-temps %t1 %t2 %t3 \ +; RUN: -r %t1,foo,px \ +; RUN: -r %t2,foo, \ +; RUN: -r %t2,bar,pl \ +; RUN: -r %t3,foo, +; RUN: llvm-dis < %t4.0.0.preopt.bc -o - | FileCheck %s --check-prefix=ASM +; RUN: llvm-nm %t4.0 | FileCheck %s --check-prefix=SYM +; RUN: llvm-objdump -d --disassemble-symbols=foo %t4.0 \ +; RUN: | FileCheck %s --check-prefix=DEF + +; ASM-NOT: module asm + +; SYM: T foo + +; DEF: leal 2(%rdi), %eax + +;--- t1.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define dso_local i32 @foo(i32 %0) { + %2 = add nsw i32 %0, 2 + ret i32 %2 +} + +;--- t2.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +module asm ".weak foo" +module asm ".equ foo, bar" + +@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 (i32)* @bar to i8*)], section "llvm.metadata" + +define internal i32 @bar(i32 %0) { + %2 = add nsw i32 %0, 1 + ret i32 %2 +} + +;--- t3.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +module asm " .global foo ; foo: "