1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[SystemZ] Define the call instructions as pseudo aliases.

Similar to r191364, but for calls.  This patch also removes the shortening
of BRASL to BRAS within a TU.  Doing that was a bit controversial internally,
since there's a strong expectation with the z assembler that WYWIWYG.

llvm-svn: 191366
This commit is contained in:
Richard Sandiford 2013-09-25 10:37:17 +00:00
parent 6f1fae507a
commit 8d56341cfb
9 changed files with 97 additions and 147 deletions

View File

@ -124,18 +124,6 @@ void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
O << *MO.getExpr(); O << *MO.getExpr();
} }
void SystemZInstPrinter::printCallOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
if (MO.isImm()) {
O << "0x";
O.write_hex(MO.getImm());
} else {
O << *MO.getExpr();
O << "@PLT";
}
}
void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum, void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
raw_ostream &O) { raw_ostream &O) {
printOperand(MI->getOperand(OpNum), O); printOperand(MI->getOperand(OpNum), O);

View File

@ -58,7 +58,6 @@ private:
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printU32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printPCRelOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printPCRelOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printAccessRegOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printAccessRegOperand(const MCInst *MI, int OpNum, raw_ostream &O);
// Print the mnemonic for a condition-code mask ("ne", "lh", etc.) // Print the mnemonic for a condition-code mask ("ne", "lh", etc.)

View File

@ -35,15 +35,6 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) {
llvm_unreachable("Unknown fixup kind!"); llvm_unreachable("Unknown fixup kind!");
} }
// If Opcode is a relaxable interprocedural reference, return the relaxed form,
// otherwise return 0.
static unsigned getRelaxedOpcode(unsigned Opcode) {
switch (Opcode) {
case SystemZ::BRAS: return SystemZ::BRASL;
}
return 0;
}
namespace { namespace {
class SystemZMCAsmBackend : public MCAsmBackend { class SystemZMCAsmBackend : public MCAsmBackend {
uint8_t OSABI; uint8_t OSABI;
@ -59,14 +50,20 @@ public:
LLVM_OVERRIDE; LLVM_OVERRIDE;
virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
uint64_t Value) const LLVM_OVERRIDE; uint64_t Value) const LLVM_OVERRIDE;
virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE; virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE {
return false;
}
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, virtual bool fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value, uint64_t Value,
const MCRelaxableFragment *Fragment, const MCRelaxableFragment *Fragment,
const MCAsmLayout &Layout) const const MCAsmLayout &Layout) const
LLVM_OVERRIDE; LLVM_OVERRIDE {
return false;
}
virtual void relaxInstruction(const MCInst &Inst, virtual void relaxInstruction(const MCInst &Inst,
MCInst &Res) const LLVM_OVERRIDE; MCInst &Res) const LLVM_OVERRIDE {
llvm_unreachable("SystemZ does do not have assembler relaxation");
}
virtual bool writeNopData(uint64_t Count, virtual bool writeNopData(uint64_t Count,
MCObjectWriter *OW) const LLVM_OVERRIDE; MCObjectWriter *OW) const LLVM_OVERRIDE;
virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const
@ -114,28 +111,6 @@ void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
} }
} }
bool SystemZMCAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
return getRelaxedOpcode(Inst.getOpcode()) != 0;
}
bool
SystemZMCAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value,
const MCRelaxableFragment *Fragment,
const MCAsmLayout &Layout) const {
// At the moment we just need to relax 16-bit fields to wider fields.
Value = extractBitsForFixup(Fixup.getKind(), Value);
return (int16_t)Value != (int64_t)Value;
}
void SystemZMCAsmBackend::relaxInstruction(const MCInst &Inst,
MCInst &Res) const {
unsigned Opcode = getRelaxedOpcode(Inst.getOpcode());
assert(Opcode && "Unexpected insn to relax");
Res = Inst;
Res.setOpcode(Opcode);
}
bool SystemZMCAsmBackend::writeNopData(uint64_t Count, bool SystemZMCAsmBackend::writeNopData(uint64_t Count,
MCObjectWriter *OW) const { MCObjectWriter *OW) const {
for (uint64_t I = 0; I != Count; ++I) for (uint64_t I = 0; I != Count; ++I)

View File

@ -79,14 +79,6 @@ private:
SmallVectorImpl<MCFixup> &Fixups) const { SmallVectorImpl<MCFixup> &Fixups) const {
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2); return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
} }
uint64_t getPLT16DBLEncoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups) const {
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT16DBL, 2);
}
uint64_t getPLT32DBLEncoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups) const {
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT32DBL, 2);
}
}; };
} }

View File

@ -27,14 +27,36 @@
using namespace llvm; using namespace llvm;
void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SystemZMCInstLower Lower(Mang, MF->getContext(), *this);
MCInst LoweredMI; MCInst LoweredMI;
switch (MI->getOpcode()) { switch (MI->getOpcode()) {
case SystemZ::Return: case SystemZ::Return:
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
break; break;
case SystemZ::CallBRASL:
LoweredMI = MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
break;
case SystemZ::CallBASR:
LoweredMI = MCInstBuilder(SystemZ::BASR)
.addReg(SystemZ::R14D)
.addReg(MI->getOperand(0).getReg());
break;
case SystemZ::CallJG:
LoweredMI = MCInstBuilder(SystemZ::JG)
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
break;
case SystemZ::CallBR:
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
break;
default: default:
SystemZMCInstLower(Mang, MF->getContext(), *this).lower(MI, LoweredMI); Lower.lower(MI, LoweredMI);
break; break;
} }
OutStreamer.EmitInstruction(LoweredMI); OutStreamer.EmitInstruction(LoweredMI);

View File

@ -223,33 +223,29 @@ defm CondStore64 : CondStores<GR64, nonvolatile_store,
// The definitions here are for the call-clobbered registers. // The definitions here are for the call-clobbered registers.
let isCall = 1, Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D, let isCall = 1, Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D,
F0D, F1D, F2D, F3D, F4D, F5D, F6D, F7D, CC], F0D, F1D, F2D, F3D, F4D, F5D, F6D, F7D, CC] in {
R1 = 14, isCodeGenOnly = 1 in { def CallBRASL : Alias<6, (outs), (ins pcrel32:$I2, variable_ops),
def BRAS : InstRI<0xA75, (outs), (ins pcrel16call:$I2, variable_ops), [(z_call pcrel32:$I2)]>;
"bras\t%r14, $I2", []>; def CallBASR : Alias<2, (outs), (ins ADDR64:$R2, variable_ops),
def BRASL : InstRIL<0xC05, (outs), (ins pcrel32call:$I2, variable_ops), [(z_call ADDR64:$R2)]>;
"brasl\t%r14, $I2", [(z_call pcrel32call:$I2)]>;
def BASR : InstRR<0x0D, (outs), (ins ADDR64:$R2, variable_ops),
"basr\t%r14, $R2", [(z_call ADDR64:$R2)]>;
} }
// Sibling calls. Indirect sibling calls must be via R1, since R2 upwards // Sibling calls. Indirect sibling calls must be via R1, since R2 upwards
// are argument registers and since branching to R0 is a no-op. // are argument registers and since branching to R0 is a no-op.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
isCodeGenOnly = 1, R1 = 15 in { def CallJG : Alias<6, (outs), (ins pcrel32:$I2),
def CallJG : InstRIL<0xC04, (outs), (ins pcrel32call:$I2), [(z_sibcall pcrel32:$I2)]>;
"jg\t$I2", [(z_sibcall pcrel32call:$I2)]>; let Uses = [R1D] in
let R2 = 1, Uses = [R1D] in def CallBR : Alias<2, (outs), (ins), [(z_sibcall R1D)]>;
def CallBR : InstRR<0x07, (outs), (ins), "br\t%r1", [(z_sibcall R1D)]>;
} }
// Define the general form of the call instructions for the asm parser. // Define the general form of the call instructions for the asm parser.
// These instructions don't hard-code %r14 as the return address register. // These instructions don't hard-code %r14 as the return address register.
def AsmBRAS : InstRI<0xA75, (outs), (ins GR64:$R1, brtarget16:$I2), def BRAS : InstRI<0xA75, (outs), (ins GR64:$R1, brtarget16:$I2),
"bras\t$R1, $I2", []>; "bras\t$R1, $I2", []>;
def AsmBRASL : InstRIL<0xC05, (outs), (ins GR64:$R1, brtarget32:$I2), def BRASL : InstRIL<0xC05, (outs), (ins GR64:$R1, brtarget32:$I2),
"brasl\t$R1, $I2", []>; "brasl\t$R1, $I2", []>;
def AsmBASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2), def BASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2),
"basr\t$R1, $R2", []>; "basr\t$R1, $R2", []>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -15,15 +15,6 @@
using namespace llvm; using namespace llvm;
// If Opcode is an interprocedural reference that can be shortened,
// return the short form, otherwise return 0.
static unsigned getShortenedInstr(unsigned Opcode) {
switch (Opcode) {
case SystemZ::BRASL: return SystemZ::BRAS;
}
return Opcode;
}
// Return the VK_* enumeration for MachineOperand target flags Flags. // Return the VK_* enumeration for MachineOperand target flags Flags.
static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) { static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) { switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
@ -39,66 +30,67 @@ SystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx,
SystemZAsmPrinter &asmprinter) SystemZAsmPrinter &asmprinter)
: Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {} : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {}
MCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO, const MCExpr *
const MCSymbol *Symbol, SystemZMCInstLower::getExpr(const MachineOperand &MO,
int64_t Offset) const { MCSymbolRefExpr::VariantKind Kind) const {
MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags()); const MCSymbol *Symbol;
bool HasOffset = true;
switch (MO.getType()) {
case MachineOperand::MO_MachineBasicBlock:
Symbol = MO.getMBB()->getSymbol();
HasOffset = false;
break;
case MachineOperand::MO_GlobalAddress:
Symbol = Mang->getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
HasOffset = false;
break;
case MachineOperand::MO_ConstantPoolIndex:
Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
break;
case MachineOperand::MO_BlockAddress:
Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
break;
default:
llvm_unreachable("unknown operand type");
}
const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx);
if (Offset) { if (HasOffset)
if (int64_t Offset = MO.getOffset()) {
const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
} }
return MCOperand::CreateExpr(Expr); return Expr;
} }
MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const { MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
switch (MO.getType()) { switch (MO.getType()) {
default:
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register: case MachineOperand::MO_Register:
return MCOperand::CreateReg(MO.getReg()); return MCOperand::CreateReg(MO.getReg());
case MachineOperand::MO_Immediate: case MachineOperand::MO_Immediate:
return MCOperand::CreateImm(MO.getImm()); return MCOperand::CreateImm(MO.getImm());
case MachineOperand::MO_MachineBasicBlock: default: {
return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
/* MO has no offset field */0); return MCOperand::CreateExpr(getExpr(MO, Kind));
case MachineOperand::MO_GlobalAddress:
return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()),
MO.getOffset());
case MachineOperand::MO_ExternalSymbol: {
StringRef Name = MO.getSymbolName();
return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name),
MO.getOffset());
}
case MachineOperand::MO_JumpTableIndex:
return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()),
/* MO has no offset field */0);
case MachineOperand::MO_ConstantPoolIndex:
return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()),
MO.getOffset());
case MachineOperand::MO_BlockAddress: {
const BlockAddress *BA = MO.getBlockAddress();
return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA),
MO.getOffset());
} }
} }
} }
void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
unsigned Opcode = MI->getOpcode(); OutMI.setOpcode(MI->getOpcode());
// When emitting binary code, start with the shortest form of an instruction
// and then relax it where necessary.
if (!AsmPrinter.OutStreamer.hasRawTextSupport())
Opcode = getShortenedInstr(Opcode);
OutMI.setOpcode(Opcode);
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
const MachineOperand &MO = MI->getOperand(I); const MachineOperand &MO = MI->getOperand(I);
// Ignore all implicit register operands. // Ignore all implicit register operands.

View File

@ -10,14 +10,13 @@
#ifndef LLVM_SYSTEMZMCINSTLOWER_H #ifndef LLVM_SYSTEMZMCINSTLOWER_H
#define LLVM_SYSTEMZMCINSTLOWER_H #define LLVM_SYSTEMZMCINSTLOWER_H
#include "llvm/MC/MCExpr.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
namespace llvm { namespace llvm {
class MCContext;
class MCInst; class MCInst;
class MCOperand; class MCOperand;
class MCSymbol;
class MachineInstr; class MachineInstr;
class MachineOperand; class MachineOperand;
class Mangler; class Mangler;
@ -38,9 +37,9 @@ public:
// Return an MCOperand for MO. // Return an MCOperand for MO.
MCOperand lowerOperand(const MachineOperand& MO) const; MCOperand lowerOperand(const MachineOperand& MO) const;
// Return an MCOperand for MO, given that it equals Symbol + Offset. // Return an MCExpr for symbolic operand MO with variant kind Kind.
MCOperand lowerSymbolOperand(const MachineOperand &MO, const MCExpr *getExpr(const MachineOperand &MO,
const MCSymbol *Symbol, int64_t Offset) const; MCSymbolRefExpr::VariantKind Kind) const;
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -395,19 +395,6 @@ def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> {
let DecoderMethod = "decodePC32DBLOperand"; let DecoderMethod = "decodePC32DBLOperand";
} }
// A PC-relative offset of a global value when the value is used as a
// call target. The offset is sign-extended and multiplied by 2.
def pcrel16call : PCRelAddress<i64, "pcrel16call", PCRel16> {
let PrintMethod = "printCallOperand";
let EncoderMethod = "getPLT16DBLEncoding";
let DecoderMethod = "decodePC16DBLOperand";
}
def pcrel32call : PCRelAddress<i64, "pcrel32call", PCRel32> {
let PrintMethod = "printCallOperand";
let EncoderMethod = "getPLT32DBLEncoding";
let DecoderMethod = "decodePC32DBLOperand";
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Addressing modes // Addressing modes
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//