Skip to content

Commit

Permalink
[AsmPrinter] refactor to support %c w/ GlobalAddress'
Browse files Browse the repository at this point in the history
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
- ClangBuiltLinux/linux#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
  • Loading branch information
nickdesaulniers committed Apr 26, 2019
1 parent 74967cb commit 7ab164c
Show file tree
Hide file tree
Showing 33 changed files with 406 additions and 86 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/AsmPrinter.h
Expand Up @@ -590,6 +590,10 @@ class AsmPrinter : public MachineFunctionPass {
virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
const char *Code) const;

/// Print the MachineOperand as a symbol. Targets with complex handling of
/// symbol references should override the base implementation.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS);

/// Print the specified operand of MI, an INLINEASM instruction, using the
/// specified assembler variant. Targets should override this to format as
/// appropriate. This method can return true if the operand is erroneous.
Expand Down
19 changes: 15 additions & 4 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
Expand Up @@ -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
Expand All @@ -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;
Expand Down
9 changes: 1 addition & 8 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Expand Up @@ -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: {
Expand Down
26 changes: 15 additions & 11 deletions llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Expand Up @@ -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>");
Expand All @@ -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:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMAsmPrinter.h
Expand Up @@ -75,6 +75,7 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {

void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);

void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
const char *ExtraCode, raw_ostream &O) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Target/AVR/AVRAsmPrinter.cpp
Expand Up @@ -42,8 +42,7 @@ class AVRAsmPrinter : public AsmPrinter {

StringRef getPassName() const override { return "AVR Assembly Printer"; }

void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = 0);
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);

bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
const char *ExtraCode, raw_ostream &O) override;
Expand All @@ -58,7 +57,7 @@ class AVRAsmPrinter : public AsmPrinter {
};

void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
raw_ostream &O, const char *Modifier) {
raw_ostream &O) {
const MachineOperand &MO = MI->getOperand(OpNo);

switch (MO.getType()) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/BPF/BPFAsmPrinter.cpp
Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
Expand Up @@ -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);
Expand Down
30 changes: 15 additions & 15 deletions llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Mips/MipsAsmPrinter.cpp
Expand Up @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
Expand Up @@ -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:
Expand Down
46 changes: 26 additions & 20 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Expand Up @@ -101,6 +101,7 @@ class PPCAsmPrinter : public AsmPrinter {
/// The \p MI would be INLINEASM ONLY.
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);

void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &O) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
Expand Down Expand Up @@ -158,6 +159,30 @@ class PPCAsmPrinter : public AsmPrinter {

} // end anonymous namespace

void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
raw_ostream &O) {
// Computing the address of a global symbol, not calling it.
const GlobalValue *GV = MO.getGlobal();
MCSymbol *SymToPrint;

// External or weakly linked global variables need non-lazily-resolved stubs
if (Subtarget->hasLazyResolverStub(GV)) {
SymToPrint = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
MachineModuleInfoImpl::StubValueTy &StubSym =
MMI->getObjFileInfo<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();
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
Expand Up @@ -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();
Expand Down
14 changes: 5 additions & 9 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Expand Up @@ -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;
}

Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/X86AsmPrinter.cpp
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/X86/X86AsmPrinter.h
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/XCore/XCoreAsmPrinter.cpp
Expand Up @@ -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() << '_'
Expand Down

0 comments on commit 7ab164c

Please sign in to comment.