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.
}
}
+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
}
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;
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: {
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>");
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:
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,
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;
};
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()) {
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;
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;
}
}
return false;
}
default:
- return true; // Unknown modifier.
+ return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
}
}
printOperand(MI, OpNo, O);
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,
};
} // 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) {
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;
}
}
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;
return;
case MachineOperand::MO_GlobalAddress:
- getSymbol(MO.getGlobal())->print(O, MAI);
+ PrintSymbolOperand(MO, O);
break;
case MachineOperand::MO_BlockAddress: {
break;
case MachineOperand::MO_GlobalAddress:
- getSymbol(MO.getGlobal())->print(O, MAI);
+ PrintSymbolOperand(MO, O);
break;
case MachineOperand::MO_MachineBasicBlock:
/// 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,
} // 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();
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;
}
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();
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;
}
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);
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ConstantPoolIndex:
PrintSymbolOperand(DispSpec, O);
+ break;
}
if (Modifier && strcmp(Modifier, "H") == 0)
// 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);
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() << '_'
--- /dev/null
+; 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
+}
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
--- /dev/null
+; 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
+}
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
}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
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
}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}