summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Desaulniers <ndesaulniers@google.com>2019-04-26 18:45:04 +0000
committerNick Desaulniers <ndesaulniers@google.com>2019-04-26 18:45:04 +0000
commit7ab164c4a427b559a7a47fa62ef365862705f950 (patch)
treec8aacfde9e16dcbd85708bf2424ce6f9c94b76aa
parent74967cb4e04c9899601b8c84901e99e797d49135 (diff)
downloadbcm5719-llvm-7ab164c4a427b559a7a47fa62ef365862705f950.tar.gz
bcm5719-llvm-7ab164c4a427b559a7a47fa62ef365862705f950.zip
[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
-rw-r--r--llvm/include/llvm/CodeGen/AsmPrinter.h4
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp19
-rw-r--r--llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp9
-rw-r--r--llvm/lib/Target/ARM/ARMAsmPrinter.cpp26
-rw-r--r--llvm/lib/Target/ARM/ARMAsmPrinter.h1
-rw-r--r--llvm/lib/Target/AVR/AVRAsmPrinter.cpp5
-rw-r--r--llvm/lib/Target/BPF/BPFAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp4
-rw-r--r--llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp30
-rw-r--r--llvm/lib/Target/Mips/MipsAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp46
-rw-r--r--llvm/lib/Target/Sparc/SparcAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp14
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp3
-rw-r--r--llvm/lib/Target/X86/X86AsmPrinter.cpp1
-rw-r--r--llvm/lib/Target/X86/X86AsmPrinter.h2
-rw-r--r--llvm/lib/Target/XCore/XCoreAsmPrinter.cpp2
-rw-r--r--llvm/test/CodeGen/AArch64/inlineasm-output-template.ll27
-rw-r--r--llvm/test/CodeGen/ARM/inlineasm-output-template.ll9
-rw-r--r--llvm/test/CodeGen/BPF/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/Hexagon/inlineasm-output-template.ll13
-rw-r--r--llvm/test/CodeGen/Lanai/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/MSP430/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/Mips/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/NVPTX/inlineasm-output-template.ll28
-rw-r--r--llvm/test/CodeGen/PowerPC/inlineasm-output-template.ll13
-rw-r--r--llvm/test/CodeGen/SPARC/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/SystemZ/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll26
-rw-r--r--llvm/test/CodeGen/X86/inline-asm-modifier-c.ll18
-rw-r--r--llvm/test/CodeGen/XCore/inlineasm-output-template.ll26
33 files changed, 406 insertions, 86 deletions
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 0307f8f6729..e62d7be9c74 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -590,6 +590,10 @@ public:
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 b092704f3cb..7721e996aca 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 591d1a8bee1..6a5166ade58 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 94ff8ee4099..152707d8159 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("<unknown operand type>");
@@ -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 c9f24e996c1..a4b37fa2331 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.h
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h
@@ -75,6 +75,7 @@ public:
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 d1a8342d948..d885050d5bf 100644
--- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
+++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
@@ -42,8 +42,7 @@ public:
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 @@ private:
};
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 5c1cd033d42..e51f51d50ce 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 1226bed1d2d..bc3d17f2d63 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 bf29c0165d2..a7d8e0805f9 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 44439137f1b..90f7ff99b4c 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 b8955ecd5e3..9ec0b0bd6db 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 438716df979..b9c7c4c53f9 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 b35e26389ff..1d24e5045fb 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -101,6 +101,7 @@ public:
/// 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 @@ public:
} // 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<MachineModuleInfoMachO>().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<MachineModuleInfoMachO>().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 411cc81c021..7e811c28e46 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 2504f36fbef..e8aeca01ea0 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 fb037b7c7b5..529bb3f2392 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 f3a2ef08096..114c09bc27f 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 fd49d154c65..a011310970b 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 12480740a4a..66445990011 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 00000000000..2e76ff89f45
--- /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 9acec42cb10..0d9300da79c 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 00000000000..8faf1bd1668
--- /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 b4ca1200740..23281a484a2 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 00000000000..9dc875c9b8d
--- /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 00000000000..9b8ca7e58e9
--- /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 00000000000..e992ddf31dd
--- /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 00000000000..cb1c6e20bca
--- /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 037acf7fe63..ea6b30dbd9a 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 00000000000..63fae9f0f38
--- /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 00000000000..563bcba1eae
--- /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 00000000000..1b62ae30131
--- /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 00000000000..d386b0676de
--- /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 00000000000..f7e73efae09
--- /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
+}
OpenPOWER on IntegriCloud