mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-16 11:30:51 +00:00
fbe7448e5d
target cannot be determined accurately. This is the case for NaCl where the sandboxing instructions are added in MC layer, after the MipsLongBranch pass. It is also the case when the code has inline assembly. Instead of calculating offset in the MipsLongBranch pass, use %hi(sym1 - sym2) and %lo(sym1 - sym2) expressions that are resolved during the fixup. This patch also deletes microMIPS test file test/CodeGen/Mips/micromips-long-branch.ll and implements microMIPS CHECKs in a much simpler way in a file test/CodeGen/Mips/longbranch.ll, together with MIPS32 and MIPS64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207656 91177308-0d34-0410-b5e6-96231b3b80d8
241 lines
8.8 KiB
C++
241 lines
8.8 KiB
C++
//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains code to lower Mips MachineInstrs to their corresponding
|
|
// MCInst records.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "MipsMCInstLower.h"
|
|
#include "MCTargetDesc/MipsBaseInfo.h"
|
|
#include "MipsAsmPrinter.h"
|
|
#include "MipsInstrInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
|
#include "llvm/IR/Mangler.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCInst.h"
|
|
|
|
using namespace llvm;
|
|
|
|
MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
|
|
: AsmPrinter(asmprinter) {}
|
|
|
|
void MipsMCInstLower::Initialize(MCContext *C) {
|
|
Ctx = C;
|
|
}
|
|
|
|
MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
|
|
MachineOperandType MOTy,
|
|
unsigned Offset) const {
|
|
MCSymbolRefExpr::VariantKind Kind;
|
|
const MCSymbol *Symbol;
|
|
|
|
switch(MO.getTargetFlags()) {
|
|
default: llvm_unreachable("Invalid target flag!");
|
|
case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break;
|
|
case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break;
|
|
case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break;
|
|
case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break;
|
|
case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break;
|
|
case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break;
|
|
case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;
|
|
case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break;
|
|
case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break;
|
|
case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break;
|
|
case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break;
|
|
case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break;
|
|
case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break;
|
|
case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break;
|
|
case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
|
|
case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
|
|
case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break;
|
|
case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
|
|
case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
|
|
case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
|
|
case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
|
|
case MipsII::MO_GOT_HI16: Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break;
|
|
case MipsII::MO_GOT_LO16: Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break;
|
|
case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break;
|
|
case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break;
|
|
}
|
|
|
|
switch (MOTy) {
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
Symbol = MO.getMBB()->getSymbol();
|
|
break;
|
|
|
|
case MachineOperand::MO_GlobalAddress:
|
|
Symbol = AsmPrinter.getSymbol(MO.getGlobal());
|
|
Offset += MO.getOffset();
|
|
break;
|
|
|
|
case MachineOperand::MO_BlockAddress:
|
|
Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
|
|
Offset += MO.getOffset();
|
|
break;
|
|
|
|
case MachineOperand::MO_ExternalSymbol:
|
|
Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
|
|
Offset += MO.getOffset();
|
|
break;
|
|
|
|
case MachineOperand::MO_JumpTableIndex:
|
|
Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
|
|
break;
|
|
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
|
Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
|
|
Offset += MO.getOffset();
|
|
break;
|
|
|
|
default:
|
|
llvm_unreachable("<unknown operand type>");
|
|
}
|
|
|
|
const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx);
|
|
|
|
if (!Offset)
|
|
return MCOperand::CreateExpr(MCSym);
|
|
|
|
// Assume offset is never negative.
|
|
assert(Offset > 0);
|
|
|
|
const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, *Ctx);
|
|
const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx);
|
|
return MCOperand::CreateExpr(Add);
|
|
}
|
|
|
|
/*
|
|
static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0,
|
|
const MCOperand &Opnd1,
|
|
const MCOperand &Opnd2 = MCOperand()) {
|
|
Inst.setOpcode(Opc);
|
|
Inst.addOperand(Opnd0);
|
|
Inst.addOperand(Opnd1);
|
|
if (Opnd2.isValid())
|
|
Inst.addOperand(Opnd2);
|
|
}
|
|
*/
|
|
|
|
MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
|
|
unsigned offset) const {
|
|
MachineOperandType MOTy = MO.getType();
|
|
|
|
switch (MOTy) {
|
|
default: llvm_unreachable("unknown operand type");
|
|
case MachineOperand::MO_Register:
|
|
// Ignore all implicit register operands.
|
|
if (MO.isImplicit()) break;
|
|
return MCOperand::CreateReg(MO.getReg());
|
|
case MachineOperand::MO_Immediate:
|
|
return MCOperand::CreateImm(MO.getImm() + offset);
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
case MachineOperand::MO_GlobalAddress:
|
|
case MachineOperand::MO_ExternalSymbol:
|
|
case MachineOperand::MO_JumpTableIndex:
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
|
case MachineOperand::MO_BlockAddress:
|
|
return LowerSymbolOperand(MO, MOTy, offset);
|
|
case MachineOperand::MO_RegisterMask:
|
|
break;
|
|
}
|
|
|
|
return MCOperand();
|
|
}
|
|
|
|
MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
|
|
MachineBasicBlock *BB2,
|
|
MCSymbolRefExpr::VariantKind Kind) const {
|
|
const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx);
|
|
const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx);
|
|
const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx);
|
|
|
|
return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx));
|
|
}
|
|
|
|
void MipsMCInstLower::
|
|
lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI, int Opcode,
|
|
MCSymbolRefExpr::VariantKind Kind) const {
|
|
OutMI.setOpcode(Opcode);
|
|
|
|
// Lower register operand.
|
|
OutMI.addOperand(LowerOperand(MI->getOperand(0)));
|
|
|
|
// Create %hi($tgt-$baltgt) or %highest($tgt-$baltgt).
|
|
OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
|
|
MI->getOperand(2).getMBB(), Kind));
|
|
}
|
|
|
|
void MipsMCInstLower::
|
|
lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
|
|
MCSymbolRefExpr::VariantKind Kind) const {
|
|
OutMI.setOpcode(Opcode);
|
|
|
|
// Lower two register operands.
|
|
for (unsigned I = 0, E = 2; I != E; ++I) {
|
|
const MachineOperand &MO = MI->getOperand(I);
|
|
OutMI.addOperand(LowerOperand(MO));
|
|
}
|
|
|
|
// Create %lo($tgt-$baltgt), %hi($tgt-$baltgt) or %higher($tgt-$baltgt).
|
|
OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
|
|
MI->getOperand(3).getMBB(), Kind));
|
|
}
|
|
|
|
bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
|
|
MCInst &OutMI) const {
|
|
switch (MI->getOpcode()) {
|
|
default:
|
|
return false;
|
|
case Mips::LONG_BRANCH_LUi:
|
|
lowerLongBranchLUi(MI, OutMI, Mips::LUi, MCSymbolRefExpr::VK_Mips_ABS_HI);
|
|
return true;
|
|
case Mips::LONG_BRANCH_LUi64:
|
|
lowerLongBranchLUi(MI, OutMI, Mips::LUi64,
|
|
MCSymbolRefExpr::VK_Mips_HIGHEST);
|
|
return true;
|
|
case Mips::LONG_BRANCH_ADDiu:
|
|
lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
|
|
MCSymbolRefExpr::VK_Mips_ABS_LO);
|
|
return true;
|
|
case Mips::LONG_BRANCH_DADDiu:
|
|
unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
|
|
if (TargetFlags == MipsII::MO_HIGHER)
|
|
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
|
MCSymbolRefExpr::VK_Mips_HIGHER);
|
|
else if (TargetFlags == MipsII::MO_ABS_HI)
|
|
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
|
MCSymbolRefExpr::VK_Mips_ABS_HI);
|
|
else if (TargetFlags == MipsII::MO_ABS_LO)
|
|
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
|
MCSymbolRefExpr::VK_Mips_ABS_LO);
|
|
else
|
|
report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
|
|
if (lowerLongBranch(MI, OutMI))
|
|
return;
|
|
|
|
OutMI.setOpcode(MI->getOpcode());
|
|
|
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
|
const MachineOperand &MO = MI->getOperand(i);
|
|
MCOperand MCOp = LowerOperand(MO);
|
|
|
|
if (MCOp.isValid())
|
|
OutMI.addOperand(MCOp);
|
|
}
|
|
}
|
|
|