diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -590,6 +590,10 @@ 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 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -599,6 +599,12 @@ } } +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 @@ } 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 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -436,14 +436,7 @@ 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.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h --- a/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -75,6 +75,7 @@ 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/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -183,10 +183,21 @@ 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 @@ 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/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp --- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp +++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp @@ -42,8 +42,7 @@ 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 @@ }; 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 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -104,7 +104,7 @@ 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 --- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -91,9 +91,7 @@ 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 --- a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp +++ b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp @@ -136,7 +136,7 @@ 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 --- a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -47,6 +47,7 @@ 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 @@ }; } // 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 @@ 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 @@ 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 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -692,7 +692,7 @@ 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 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -2230,7 +2230,7 @@ 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 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -101,6 +101,7 @@ /// 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 @@ } // 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 @@ 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 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -357,7 +357,7 @@ 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 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -620,15 +620,11 @@ 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 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -407,8 +407,7 @@ 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.h b/llvm/lib/Target/X86/X86AsmPrinter.h --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -102,7 +102,7 @@ // 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/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -299,6 +299,7 @@ case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ConstantPoolIndex: PrintSymbolOperand(DispSpec, O); + break; } if (Modifier && strcmp(Modifier, "H") == 0) diff --git a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp --- a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -213,7 +213,7 @@ 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 --- /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 --- a/llvm/test/CodeGen/ARM/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/ARM/inlineasm-output-template.ll @@ -8,6 +8,15 @@ 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/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/BPF/inlineasm-output-template.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/BPF/inlineasm-output-template.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/BPF/inlineasm-output-template.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -mtriple=bpfel-linux-gnu < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,10 +8,19 @@ ret i32 42 } -; Test that %n works with immediates +; Test that %c works with global address ; CHECK-LABEL: test_inlineasm_c_output_template1 -; CHECK: #TEST -42 +; 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 --- a/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll @@ -8,10 +8,19 @@ 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 --- /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 --- /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/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/Mips/inlineasm-output-template.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/Mips/inlineasm-output-template.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/Mips/inlineasm-output-template.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -mtriple=mips64el-linux-gnu < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,10 +8,19 @@ ret i32 42 } -; Test that %n works with immediates +; Test that %c works with global address ; CHECK-LABEL: test_inlineasm_c_output_template1 -; CHECK: #TEST -42 +; 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 --- /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 --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll @@ -8,10 +8,19 @@ 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 --- /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/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -mtriple=s390x-linux-gnu < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,6 +8,15 @@ 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/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -mtriple=wasm32 < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,6 +8,15 @@ 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/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/X86/inline-asm-modifier-c.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/X86/inline-asm-modifier-c.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/X86/inline-asm-modifier-c.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -mtriple=x86_64-linux-gnu < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,10 +8,11 @@ ret i32 42 } -; Test that %n works with immediates +; Test that %c works with global address ; CHECK-LABEL: test_inlineasm_c_output_template1 -; CHECK: #TEST -42 +; 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:n}", "i"(i32 42) + tail call void asm sideeffect "#TEST ${0:c}", "i"(i32* nonnull @baz) ret i32 42 } diff --git a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll b/llvm/test/CodeGen/XCore/inlineasm-output-template.ll copy from llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll copy to llvm/test/CodeGen/XCore/inlineasm-output-template.ll --- a/llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll +++ b/llvm/test/CodeGen/XCore/inlineasm-output-template.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=ppc32-- < %s | FileCheck %s +; RUN: llc -march=xcore < %s | FileCheck %s ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 @@ -8,6 +8,15 @@ 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