Files
llvm-6502/lib/Target/PowerPC/PPCMCInstLower.cpp
Ulrich Weigand 027e94479c [PowerPC] Optimize @ha/@l constructs
This patch adds support for having the assembler optimize fixups
to constructs like "symbol@ha" or "symbol@l" if "symbol" can be
resolved at assembler time.

This optimization is already present in the PPCMCExpr.cpp code
for handling PPC_HA16/PPC_LO16 target expressions.  However,
those target expression were used only on Darwin targets.

This patch changes target expression code so that they are
usable also with the GNU assembler (using the @ha / @l syntax
instead of the ha16() / lo16() syntax), and changes the
MCInst lowering code to generate those target expressions
where appropriate.

It also changes the asm parser to generate HA16/LO16 target
expressions when parsing assembler source that uses the
@ha / @l modifiers.  The effect is that now the above-
mentioned optimization automatically becomes available
for those situations too.
 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184436 91177308-0d34-0410-b5e6-96231b3b80d8
2013-06-20 16:23:52 +00:00

204 lines
6.7 KiB
C++

//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an 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 PPC MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//
#include "PPC.h"
#include "MCTargetDesc/PPCMCExpr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/Mangler.h"
using namespace llvm;
static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
}
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
MCContext &Ctx = AP.OutContext;
SmallString<128> Name;
if (!MO.isGlobal()) {
assert(MO.isSymbol() && "Isn't a symbol reference");
Name += AP.MAI->getGlobalPrefix();
Name += MO.getSymbolName();
} else {
const GlobalValue *GV = MO.getGlobal();
bool isImplicitlyPrivate = false;
if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB ||
(MO.getTargetFlags() & PPCII::MO_NLP_FLAG))
isImplicitlyPrivate = true;
AP.Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
}
// If the target flags on the operand changes the name of the symbol, do that
// before we return the symbol.
if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) {
Name += "$stub";
const char *PGP = AP.MAI->getPrivateGlobalPrefix();
const char *Prefix = "";
if (!Name.startswith(PGP)) {
// http://llvm.org/bugs/show_bug.cgi?id=15763
// all stubs and lazy_ptrs should be local symbols, which need leading 'L'
Prefix = PGP;
}
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Twine(Prefix) + Twine(Name));
MachineModuleInfoImpl::StubValueTy &StubSym =
getMachOMMI(AP).getFnStubEntry(Sym);
if (StubSym.getPointer())
return Sym;
if (MO.isGlobal()) {
StubSym =
MachineModuleInfoImpl::
StubValueTy(AP.Mang->getSymbol(MO.getGlobal()),
!MO.getGlobal()->hasInternalLinkage());
} else {
Name.erase(Name.end()-5, Name.end());
StubSym =
MachineModuleInfoImpl::
StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false);
}
return Sym;
}
// If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
// then add the suffix.
if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
Name += "$non_lazy_ptr";
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
MachineModuleInfoMachO &MachO = getMachOMMI(AP);
MachineModuleInfoImpl::StubValueTy &StubSym =
(MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ?
MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);
if (StubSym.getPointer() == 0) {
assert(MO.isGlobal() && "Extern symbol not handled yet");
StubSym = MachineModuleInfoImpl::
StubValueTy(AP.Mang->getSymbol(MO.getGlobal()),
!MO.getGlobal()->hasInternalLinkage());
}
return Sym;
}
return Ctx.GetOrCreateSymbol(Name.str());
}
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
AsmPrinter &Printer, bool isDarwin) {
MCContext &Ctx = Printer.OutContext;
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
switch (access) {
case PPCII::MO_TPREL16_HA:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_HA;
break;
case PPCII::MO_TPREL16_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_LO;
break;
case PPCII::MO_DTPREL16_LO:
RefKind = MCSymbolRefExpr::VK_PPC_DTPREL16_LO;
break;
case PPCII::MO_TLSLD16_LO:
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO;
break;
case PPCII::MO_TOC16_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TOC16_LO;
break;
}
const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::CreateAdd(Expr,
MCConstantExpr::Create(MO.getOffset(), Ctx),
Ctx);
// Subtract off the PIC base if required.
if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
}
// Add ha16() / lo16() markers if required.
switch (access) {
case PPCII::MO_HA16:
Expr = PPCMCExpr::CreateHa16(Expr, Ctx);
break;
case PPCII::MO_LO16:
Expr = PPCMCExpr::CreateLo16(Expr, Ctx);
break;
}
return MCOperand::CreateExpr(Expr);
}
void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP, bool isDarwin) {
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp;
switch (MO.getType()) {
default:
MI->dump();
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
assert(!MO.getSubReg() && "Subregs should be eliminated!");
MCOp = MCOperand::CreateReg(MO.getReg());
break;
case MachineOperand::MO_Immediate:
MCOp = MCOperand::CreateImm(MO.getImm());
break;
case MachineOperand::MO_MachineBasicBlock:
MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
MO.getMBB()->getSymbol(), AP.OutContext));
break;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
break;
case MachineOperand::MO_JumpTableIndex:
MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
break;
case MachineOperand::MO_ConstantPoolIndex:
MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
break;
case MachineOperand::MO_BlockAddress:
MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
isDarwin);
break;
case MachineOperand::MO_RegisterMask:
continue;
}
OutMI.addOperand(MCOp);
}
}