mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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
This commit is contained in:
parent
18bf91733a
commit
02a0e7f7fc
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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: {
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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: {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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() << '_'
|
||||
|
27
test/CodeGen/AArch64/inlineasm-output-template.ll
Normal file
27
test/CodeGen/AArch64/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
@ -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
|
||||
|
26
test/CodeGen/BPF/inlineasm-output-template.ll
Normal file
26
test/CodeGen/BPF/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
@ -8,10 +8,19 @@ define dso_local i32 @test_inlineasm_c_output_template0() {
|
||||
ret i32 42
|
||||
}
|
||||
|
||||
; Test that %n works with immediates
|
||||
; CHECK-LABEL: test_inlineasm_c_output_template1
|
||||
; CHECK: //TEST -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
|
||||
}
|
||||
|
26
test/CodeGen/Lanai/inlineasm-output-template.ll
Normal file
26
test/CodeGen/Lanai/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
26
test/CodeGen/MSP430/inlineasm-output-template.ll
Normal file
26
test/CodeGen/MSP430/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
26
test/CodeGen/Mips/inlineasm-output-template.ll
Normal file
26
test/CodeGen/Mips/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
28
test/CodeGen/NVPTX/inlineasm-output-template.ll
Normal file
28
test/CodeGen/NVPTX/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
@ -8,10 +8,19 @@ define dso_local i32 @test_inlineasm_c_output_template0() {
|
||||
ret i32 42
|
||||
}
|
||||
|
||||
; Test that %n works with immediates
|
||||
; CHECK-LABEL: test_inlineasm_c_output_template1
|
||||
; CHECK: #TEST -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
|
||||
}
|
||||
|
26
test/CodeGen/SPARC/inlineasm-output-template.ll
Normal file
26
test/CodeGen/SPARC/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
26
test/CodeGen/SystemZ/inlineasm-output-template.ll
Normal file
26
test/CodeGen/SystemZ/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
26
test/CodeGen/WebAssembly/inlineasm-output-template.ll
Normal file
26
test/CodeGen/WebAssembly/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
18
test/CodeGen/X86/inline-asm-modifier-c.ll
Normal file
18
test/CodeGen/X86/inline-asm-modifier-c.ll
Normal file
@ -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
|
||||
}
|
26
test/CodeGen/XCore/inlineasm-output-template.ll
Normal file
26
test/CodeGen/XCore/inlineasm-output-template.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user