From 7ab164c4a427b559a7a47fa62ef365862705f950 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 26 Apr 2019 18:45:04 +0000 Subject: [PATCH] [AsmPrinter] refactor to support %c w/ GlobalAddress' Summary: Targets like ARM, MSP430, PPC, and SystemZ have complex behavior when printing the address of a MachineOperand::MO_GlobalAddress. Move that handling into a new overriden method in each base class. A virtual method was added to the base class for handling the generic case. Refactors a few subclasses to support the target independent %a, %c, and %n. The patch also contains small cleanups for AVRAsmPrinter and SystemZAsmPrinter. It seems that NVPTXTargetLowering is possibly missing some logic to transform GlobalAddressSDNodes for TargetLowering::LowerAsmOperandForConstraint to handle with "i" extended inline assembly asm constraints. Fixes: - https://bugs.llvm.org/show_bug.cgi?id=41402 - https://github.com/ClangBuiltLinux/linux/issues/449 Reviewers: echristo, void Reviewed By: void Subscribers: void, craig.topper, jholewinski, dschuff, jyknight, dylanmckay, sdardis, nemanjai, javed.absar, sbc100, jgravelle-google, eraman, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, jrtc27, atanasyan, jsji, llvm-commits, kees, tpimh, nathanchance, peter.smith, srhines Tags: #llvm Differential Revision: https://reviews.llvm.org/D60887 llvm-svn: 359337 --- llvm/include/llvm/CodeGen/AsmPrinter.h | 4 ++ .../AsmPrinter/AsmPrinterInlineAsm.cpp | 19 ++++++-- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 9 +--- llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 26 ++++++----- llvm/lib/Target/ARM/ARMAsmPrinter.h | 1 + llvm/lib/Target/AVR/AVRAsmPrinter.cpp | 5 +- llvm/lib/Target/BPF/BPFAsmPrinter.cpp | 2 +- llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp | 4 +- llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp | 2 +- llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp | 30 ++++++------ llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 2 +- llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 2 +- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 46 +++++++++++-------- llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 2 +- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 14 ++---- .../WebAssembly/WebAssemblyAsmPrinter.cpp | 3 +- llvm/lib/Target/X86/X86AsmPrinter.cpp | 1 + llvm/lib/Target/X86/X86AsmPrinter.h | 2 +- llvm/lib/Target/XCore/XCoreAsmPrinter.cpp | 2 +- .../AArch64/inlineasm-output-template.ll | 27 +++++++++++ .../CodeGen/ARM/inlineasm-output-template.ll | 9 ++++ .../CodeGen/BPF/inlineasm-output-template.ll | 26 +++++++++++ .../Hexagon/inlineasm-output-template.ll | 13 +++++- .../Lanai/inlineasm-output-template.ll | 26 +++++++++++ .../MSP430/inlineasm-output-template.ll | 26 +++++++++++ .../CodeGen/Mips/inlineasm-output-template.ll | 26 +++++++++++ .../NVPTX/inlineasm-output-template.ll | 28 +++++++++++ .../PowerPC/inlineasm-output-template.ll | 13 +++++- .../SPARC/inlineasm-output-template.ll | 26 +++++++++++ .../SystemZ/inlineasm-output-template.ll | 26 +++++++++++ .../WebAssembly/inlineasm-output-template.ll | 26 +++++++++++ .../test/CodeGen/X86/inline-asm-modifier-c.ll | 18 ++++++++ .../XCore/inlineasm-output-template.ll | 26 +++++++++++ 33 files changed, 406 insertions(+), 86 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/BPF/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/Lanai/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/MSP430/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/Mips/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/NVPTX/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/SPARC/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll create mode 100644 llvm/test/CodeGen/X86/inline-asm-modifier-c.ll create mode 100644 llvm/test/CodeGen/XCore/inlineasm-output-template.ll diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index 0307f8f67298d..e62d7be9c74db 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -590,6 +590,10 @@ class AsmPrinter : public MachineFunctionPass { virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, const char *Code) const; + /// Print the MachineOperand as a symbol. Targets with complex handling of + /// symbol references should override the base implementation. + virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS); + /// Print the specified operand of MI, an INLINEASM instruction, using the /// specified assembler variant. Targets should override this to format as /// appropriate. This method can return true if the operand is erroneous. diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index b092704f3cb75..7721e996aca5a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -599,6 +599,12 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, } } +void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) { + assert(MO.isGlobal() && "caller should check MO.isGlobal"); + getSymbol(MO.getGlobal())->print(OS, MAI); + printOffset(MO.getOffset(), OS); +} + /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM /// instruction, using the specified assembler variant. Targets should /// override this to format as appropriate for machine specific ExtraCodes @@ -621,10 +627,15 @@ bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } LLVM_FALLTHROUGH; // GCC allows '%a' to behave like '%c' with immediates. case 'c': // Substitute immediate value without immediate syntax - if (!MO.isImm()) - return true; - O << MO.getImm(); - return false; + if (MO.isImm()) { + O << MO.getImm(); + return false; + } + if (MO.isGlobal()) { + PrintSymbolOperand(MO, O); + return false; + } + return true; case 'n': // Negate the immediate constant. if (!MO.isImm()) return true; diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 591d1a8bee191..6a5166ade5873 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -436,14 +436,7 @@ void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum, break; } case MachineOperand::MO_GlobalAddress: { - const GlobalValue *GV = MO.getGlobal(); - MCSymbol *Sym = getSymbol(GV); - - // FIXME: Can we get anything other than a plain symbol here? - assert(!MO.getTargetFlags() && "Unknown operand target flag!"); - - Sym->print(O, MAI); - printOffset(MO.getOffset(), O); + PrintSymbolOperand(MO, O); break; } case MachineOperand::MO_BlockAddress: { diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 94ff8ee40999d..152707d81591b 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -183,10 +183,21 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { return false; } +void ARMAsmPrinter::PrintSymbolOperand(const MachineOperand &MO, + raw_ostream &O) { + assert(MO.isGlobal() && "caller should check MO.isGlobal"); + unsigned TF = MO.getTargetFlags(); + if (TF & ARMII::MO_LO16) + O << ":lower16:"; + else if (TF & ARMII::MO_HI16) + O << ":upper16:"; + GetARMGVSymbol(MO.getGlobal(), TF)->print(O, MAI); + printOffset(MO.getOffset(), O); +} + void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNum); - unsigned TF = MO.getTargetFlags(); switch (MO.getType()) { default: llvm_unreachable(""); @@ -203,27 +214,20 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, break; } case MachineOperand::MO_Immediate: { - int64_t Imm = MO.getImm(); O << '#'; + unsigned TF = MO.getTargetFlags(); if (TF == ARMII::MO_LO16) O << ":lower16:"; else if (TF == ARMII::MO_HI16) O << ":upper16:"; - O << Imm; + O << MO.getImm(); break; } case MachineOperand::MO_MachineBasicBlock: MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: { - const GlobalValue *GV = MO.getGlobal(); - if (TF & ARMII::MO_LO16) - O << ":lower16:"; - else if (TF & ARMII::MO_HI16) - O << ":upper16:"; - GetARMGVSymbol(GV, TF)->print(O, MAI); - - printOffset(MO.getOffset(), O); + PrintSymbolOperand(MO, O); break; } case MachineOperand::MO_ConstantPoolIndex: diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h index c9f24e996c1b8..a4b37fa2331f6 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -75,6 +75,7 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, diff --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp index d1a8342d9486c..d885050d5bf03 100644 --- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp +++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp @@ -42,8 +42,7 @@ class AVRAsmPrinter : public AsmPrinter { StringRef getPassName() const override { return "AVR Assembly Printer"; } - void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O, - const char *Modifier = 0); + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override; @@ -58,7 +57,7 @@ class AVRAsmPrinter : public AsmPrinter { }; void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier) { + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp index 5c1cd033d42d5..e51f51d50ce72 100644 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -104,7 +104,7 @@ void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) { if (ExtraCode && ExtraCode[0]) - return true; // BPF does not have special modifiers + return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); printOperand(MI, OpNo, O); return false; diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp index 1226bed1d2da0..bc3d17f2d6319 100644 --- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -91,9 +91,7 @@ void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, GetCPISymbol(MO.getIndex())->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: - // Computing the address of a global symbol, not calling it. - getSymbol(MO.getGlobal())->print(O, MAI); - printOffset(MO.getOffset(), O); + PrintSymbolOperand(MO, O); return; } } diff --git a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp index bf29c0165d20b..a7d8e0805f9ab 100644 --- a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp +++ b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp @@ -136,7 +136,7 @@ bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, return false; } default: - return true; // Unknown modifier. + return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); } } printOperand(MI, OpNo, O); diff --git a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp index 44439137f1bb9..90f7ff99b4cd8 100644 --- a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -47,6 +47,7 @@ namespace { bool runOnMachineFunction(MachineFunction &MF) override; + void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = nullptr); void printSrcMemOperand(const MachineInstr *MI, int OpNum, @@ -61,6 +62,17 @@ namespace { }; } // end of anonymous namespace +void MSP430AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, + raw_ostream &O) { + uint64_t Offset = MO.getOffset(); + if (Offset) + O << '(' << Offset << '+'; + + getSymbol(MO.getGlobal())->print(O, MAI); + + if (Offset) + O << ')'; +} void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char *Modifier) { @@ -79,25 +91,13 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - uint64_t Offset = MO.getOffset(); - // If the global address expression is a part of displacement field with a // register base, we should not emit any prefix symbol here, e.g. - // mov.w &foo, r1 - // vs // mov.w glb(r1), r2 // Otherwise (!) msp430-as will silently miscompile the output :( if (!Modifier || strcmp(Modifier, "nohash")) - O << (isMemOp ? '&' : '#'); - if (Offset) - O << '(' << Offset << '+'; - - getSymbol(MO.getGlobal())->print(O, MAI); - - if (Offset) - O << ')'; - + O << '#'; + PrintSymbolOperand(MO, O); return; } } @@ -129,7 +129,7 @@ bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); printOperand(MI, OpNo, O); return false; diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index b8955ecd5e34d..9ec0b0bd6db45 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -692,7 +692,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, return; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(O, MAI); + PrintSymbolOperand(MO, O); break; case MachineOperand::MO_BlockAddress: { diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index 438716df97944..b9c7c4c53f954 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -2230,7 +2230,7 @@ void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, break; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(O, MAI); + PrintSymbolOperand(MO, O); break; case MachineOperand::MO_MachineBasicBlock: diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index b35e26389ffd2..1d24e5045fb0f 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -101,6 +101,7 @@ class PPCAsmPrinter : public AsmPrinter { /// The \p MI would be INLINEASM ONLY. void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); + void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, @@ -158,6 +159,30 @@ class PPCAsmPrinter : public AsmPrinter { } // end anonymous namespace +void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO, + raw_ostream &O) { + // Computing the address of a global symbol, not calling it. + const GlobalValue *GV = MO.getGlobal(); + MCSymbol *SymToPrint; + + // External or weakly linked global variables need non-lazily-resolved stubs + if (Subtarget->hasLazyResolverStub(GV)) { + SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + MachineModuleInfoImpl::StubValueTy &StubSym = + MMI->getObjFileInfo().getGVStubEntry( + SymToPrint); + if (!StubSym.getPointer()) + StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), + !GV->hasInternalLinkage()); + } else { + SymToPrint = getSymbol(GV); + } + + SymToPrint->print(O, MAI); + + printOffset(MO.getOffset(), O); +} + void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { const DataLayout &DL = getDataLayout(); @@ -190,26 +215,7 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: { - // Computing the address of a global symbol, not calling it. - const GlobalValue *GV = MO.getGlobal(); - MCSymbol *SymToPrint; - - // External or weakly linked global variables need non-lazily-resolved stubs - if (Subtarget->hasLazyResolverStub(GV)) { - SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); - MachineModuleInfoImpl::StubValueTy &StubSym = - MMI->getObjFileInfo().getGVStubEntry( - SymToPrint); - if (!StubSym.getPointer()) - StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), - !GV->hasInternalLinkage()); - } else { - SymToPrint = getSymbol(GV); - } - - SymToPrint->print(O, MAI); - - printOffset(MO.getOffset(), O); + PrintSymbolOperand(MO, O); return; } diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp index 411cc81c0213b..7e811c28e4617 100644 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -357,7 +357,7 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(O, MAI); + PrintSymbolOperand(MO, O); break; case MachineOperand::MO_BlockAddress: O << GetBlockAddressSymbol(MO.getBlockAddress())->getName(); diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 2504f36fbefa7..e8aeca01ea0a0 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -620,15 +620,11 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) { - if (ExtraCode && *ExtraCode == 'n') { - if (!MI->getOperand(OpNo).isImm()) - return true; - OS << -int64_t(MI->getOperand(OpNo).getImm()); - } else { - SystemZMCInstLower Lower(MF->getContext(), *this); - MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); - SystemZInstPrinter::printOperand(MO, MAI, OS); - } + if (ExtraCode) + return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); + SystemZMCInstLower Lower(MF->getContext(), *this); + MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); + SystemZInstPrinter::printOperand(MO, MAI, OS); return false; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index fb037b7c7b5f2..529bb3f23924e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -407,8 +407,7 @@ bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI, OS << regToString(MO); return false; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(OS, MAI); - printOffset(MO.getOffset(), OS); + PrintSymbolOperand(MO, OS); return false; case MachineOperand::MO_ExternalSymbol: GetExternalSymbolSymbol(MO.getSymbolName())->print(OS, MAI); diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index f3a2ef08096e8..114c09bc27f50 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -299,6 +299,7 @@ void X86AsmPrinter::PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo, case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ConstantPoolIndex: PrintSymbolOperand(DispSpec, O); + break; } if (Modifier && strcmp(Modifier, "H") == 0) diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h index fd49d154c6592..a011310970b3f 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -102,7 +102,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { // Choose between emitting .seh_ directives and .cv_fpo_ directives. void EmitSEHInstruction(const MachineInstr *MI); - void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O); + void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O, const char *Modifier); diff --git a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp index 12480740a4a4c..66445990011ce 100644 --- a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -213,7 +213,7 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, MO.getMBB()->getSymbol()->print(O, MAI); break; case MachineOperand::MO_GlobalAddress: - getSymbol(MO.getGlobal())->print(O, MAI); + PrintSymbolOperand(MO, O); break; case MachineOperand::MO_ConstantPoolIndex: O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' diff --git a/llvm/test/CodeGen/AArch64/inlineasm-output-template.ll b/llvm/test/CodeGen/AArch64/inlineasm-output-template.ll new file mode 100644 index 0000000000000..2e76ff89f4521 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/inlineasm-output-template.ll @@ -0,0 +1,27 @@ +; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s + + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "//TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1: +; CHECK: TEST {{_?}}baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "//TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 43 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "//TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/ARM/inlineasm-output-template.ll b/llvm/test/CodeGen/ARM/inlineasm-output-template.ll index 9acec42cb1020..0d9300da79c98 100644 --- a/llvm/test/CodeGen/ARM/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/ARM/inlineasm-output-template.ll @@ -8,6 +8,15 @@ define dso_local i32 @test_inlineasm_c_output_template0() { ret i32 42 } +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: @TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "@TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + ; Test that %n works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template1 ; CHECK: @TEST -42 diff --git a/llvm/test/CodeGen/BPF/inlineasm-output-template.ll b/llvm/test/CodeGen/BPF/inlineasm-output-template.ll new file mode 100644 index 0000000000000..8faf1bd1668c2 --- /dev/null +++ b/llvm/test/CodeGen/BPF/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=bpfel-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: #TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll b/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll index b4ca12007409f..23281a484a2bb 100644 --- a/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll @@ -8,10 +8,19 @@ define dso_local i32 @test_inlineasm_c_output_template0() { ret i32 42 } +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1: +; CHECK: TEST {{_?}}baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "//TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 43 +} + ; Test that %n works with immediates -; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK-LABEL: test_inlineasm_c_output_template2 ; CHECK: //TEST -42 -define dso_local i32 @test_inlineasm_c_output_template1() { +define dso_local i32 @test_inlineasm_c_output_template2() { tail call void asm sideeffect "//TEST ${0:n}", "i"(i32 42) ret i32 42 } diff --git a/llvm/test/CodeGen/Lanai/inlineasm-output-template.ll b/llvm/test/CodeGen/Lanai/inlineasm-output-template.ll new file mode 100644 index 0000000000000..9dc875c9b8dfe --- /dev/null +++ b/llvm/test/CodeGen/Lanai/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=lanai-linux-gnueabi < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: !TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "!TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: !TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "!TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: !TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "!TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/MSP430/inlineasm-output-template.ll b/llvm/test/CodeGen/MSP430/inlineasm-output-template.ll new file mode 100644 index 0000000000000..9b8ca7e58e963 --- /dev/null +++ b/llvm/test/CodeGen/MSP430/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=msp430-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: ;TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect ";TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: ;TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect ";TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: ;TEST -42 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect ";TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/Mips/inlineasm-output-template.ll b/llvm/test/CodeGen/Mips/inlineasm-output-template.ll new file mode 100644 index 0000000000000..e992ddf31dd45 --- /dev/null +++ b/llvm/test/CodeGen/Mips/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=mips64el-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: #TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/NVPTX/inlineasm-output-template.ll b/llvm/test/CodeGen/NVPTX/inlineasm-output-template.ll new file mode 100644 index 0000000000000..cb1c6e20bcac9 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/inlineasm-output-template.ll @@ -0,0 +1,28 @@ +; RUN: llc -march=nvptx < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: //TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "//TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; FIXME: seems this case isn't handled properly by +; SelectionDAG TargetLowering::LowerAsmOperandForConstraint? +; check: test_inlineasm_c_output_template1 +; check: //TEST baz +;@baz = internal global i32 0, align 4 +;define dso_local i32 @test_inlineasm_c_output_template1() { +; tail call void asm sideeffect "//TEST ${0:c}", "i"(i32* nonnull @baz) +; ret i32 42 +;} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: //TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "//TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll index 037acf7fe6373..ea6b30dbd9a4b 100644 --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll @@ -8,10 +8,19 @@ define dso_local i32 @test_inlineasm_c_output_template0() { ret i32 42 } +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1: +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 43 +} + ; Test that %n works with immediates -; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK-LABEL: test_inlineasm_c_output_template2 ; CHECK: #TEST -42 -define dso_local i32 @test_inlineasm_c_output_template1() { +define dso_local i32 @test_inlineasm_c_output_template2() { tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) ret i32 42 } diff --git a/llvm/test/CodeGen/SPARC/inlineasm-output-template.ll b/llvm/test/CodeGen/SPARC/inlineasm-output-template.ll new file mode 100644 index 0000000000000..63fae9f0f38f1 --- /dev/null +++ b/llvm/test/CodeGen/SPARC/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=sparc-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: !TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "!TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: !TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "!TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: !TEST -42 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "!TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll b/llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll new file mode 100644 index 0000000000000..563bcba1eaee2 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=s390x-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST -42 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll b/llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll new file mode 100644 index 0000000000000..1b62ae3013152 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -mtriple=wasm32 < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST -42 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) + ret i32 42 +} diff --git a/llvm/test/CodeGen/X86/inline-asm-modifier-c.ll b/llvm/test/CodeGen/X86/inline-asm-modifier-c.ll new file mode 100644 index 0000000000000..d386b0676de31 --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-modifier-c.ll @@ -0,0 +1,18 @@ +; RUN: llc -mtriple=x86_64-linux-gnu < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} diff --git a/llvm/test/CodeGen/XCore/inlineasm-output-template.ll b/llvm/test/CodeGen/XCore/inlineasm-output-template.ll new file mode 100644 index 0000000000000..f7e73efae0906 --- /dev/null +++ b/llvm/test/CodeGen/XCore/inlineasm-output-template.ll @@ -0,0 +1,26 @@ +; RUN: llc -march=xcore < %s | FileCheck %s + +; Test that %c works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template0 +; CHECK: #TEST 42 +define dso_local i32 @test_inlineasm_c_output_template0() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32 42) + ret i32 42 +} + +; Test that %c works with global address +; CHECK-LABEL: test_inlineasm_c_output_template2 +; CHECK: #TEST baz +@baz = internal global i32 0, align 4 +define dso_local i32 @test_inlineasm_c_output_template2() { + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) + ret i32 42 +} + +; Test that %n works with immediates +; CHECK-LABEL: test_inlineasm_c_output_template1 +; CHECK: #TEST -42 +define dso_local i32 @test_inlineasm_c_output_template1() { + tail call void asm sideeffect "#TEST ${0:n}", "i"(i32 42) + ret i32 42 +}