mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
ffdf511cf4
This patch adds support for some new relocation models to the ARM backend: * Read-only position independence (ROPI): Code and read-only data is accessed PC-relative. The offsets between all code and RO data sections are known at static link time. This does not affect read-write data. * Read-write position independence (RWPI): Read-write data is accessed relative to the static base register (r9). The offsets between all writeable data sections are known at static link time. This does not affect read-only data. These two modes are independent (they specify how different objects should be addressed), so they can be used individually or together. They are otherwise the same as the "static" relocation model, and are not compatible with SysV-style PIC using a global offset table. These modes are normally used by bare-metal systems or systems with small real-time operating systems. They are designed to avoid the need for a dynamic linker, the only initialisation required is setting r9 to an appropriate value for RWPI code. I have only added support to SelectionDAG, not FastISel, because FastISel is currently disabled for bare-metal targets where these modes would be used. Differential Revision: https://reviews.llvm.org/D23195 llvm-svn: 278015
271 lines
10 KiB
C++
271 lines
10 KiB
C++
//===-- ARMConstantPoolValue.cpp - ARM constantpool value -----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the ARM specific constantpool value class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ARMConstantPoolValue.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/IR/Constant.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/GlobalValue.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cstdlib>
|
|
using namespace llvm;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ARMConstantPoolValue
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id,
|
|
ARMCP::ARMCPKind kind,
|
|
unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier modifier,
|
|
bool addCurrentAddress)
|
|
: MachineConstantPoolValue(Ty), LabelId(id), Kind(kind),
|
|
PCAdjust(PCAdj), Modifier(modifier),
|
|
AddCurrentAddress(addCurrentAddress) {}
|
|
|
|
ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id,
|
|
ARMCP::ARMCPKind kind,
|
|
unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier modifier,
|
|
bool addCurrentAddress)
|
|
: MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
|
|
LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier),
|
|
AddCurrentAddress(addCurrentAddress) {}
|
|
|
|
ARMConstantPoolValue::~ARMConstantPoolValue() {}
|
|
|
|
const char *ARMConstantPoolValue::getModifierText() const {
|
|
switch (Modifier) {
|
|
// FIXME: Are these case sensitive? It'd be nice to lower-case all the
|
|
// strings if that's legal.
|
|
case ARMCP::no_modifier:
|
|
return "none";
|
|
case ARMCP::TLSGD:
|
|
return "tlsgd";
|
|
case ARMCP::GOT_PREL:
|
|
return "GOT_PREL";
|
|
case ARMCP::GOTTPOFF:
|
|
return "gottpoff";
|
|
case ARMCP::TPOFF:
|
|
return "tpoff";
|
|
case ARMCP::SBREL:
|
|
return "SBREL";
|
|
case ARMCP::SECREL:
|
|
return "secrel32";
|
|
}
|
|
llvm_unreachable("Unknown modifier!");
|
|
}
|
|
|
|
int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
|
unsigned Alignment) {
|
|
llvm_unreachable("Shouldn't be calling this directly!");
|
|
}
|
|
|
|
void
|
|
ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
|
ID.AddInteger(LabelId);
|
|
ID.AddInteger(PCAdjust);
|
|
}
|
|
|
|
bool
|
|
ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
|
|
if (ACPV->Kind == Kind &&
|
|
ACPV->PCAdjust == PCAdjust &&
|
|
ACPV->Modifier == Modifier &&
|
|
ACPV->LabelId == LabelId &&
|
|
ACPV->AddCurrentAddress == AddCurrentAddress) {
|
|
// Two PC relative constpool entries containing the same GV address or
|
|
// external symbols. FIXME: What about blockaddress?
|
|
if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LLVM_DUMP_METHOD void ARMConstantPoolValue::dump() const {
|
|
errs() << " " << *this;
|
|
}
|
|
|
|
void ARMConstantPoolValue::print(raw_ostream &O) const {
|
|
if (Modifier) O << "(" << getModifierText() << ")";
|
|
if (PCAdjust != 0) {
|
|
O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
|
|
if (AddCurrentAddress) O << "-.";
|
|
O << ")";
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ARMConstantPoolConstant
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty,
|
|
const Constant *C,
|
|
unsigned ID,
|
|
ARMCP::ARMCPKind Kind,
|
|
unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier Modifier,
|
|
bool AddCurrentAddress)
|
|
: ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress),
|
|
CVal(C) {}
|
|
|
|
ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
|
|
unsigned ID,
|
|
ARMCP::ARMCPKind Kind,
|
|
unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier Modifier,
|
|
bool AddCurrentAddress)
|
|
: ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier,
|
|
AddCurrentAddress),
|
|
CVal(C) {}
|
|
|
|
ARMConstantPoolConstant *
|
|
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
|
|
return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
|
|
ARMCP::no_modifier, false);
|
|
}
|
|
|
|
ARMConstantPoolConstant *
|
|
ARMConstantPoolConstant::Create(const GlobalValue *GV,
|
|
ARMCP::ARMCPModifier Modifier) {
|
|
return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
|
|
GV, 0, ARMCP::CPValue, 0,
|
|
Modifier, false);
|
|
}
|
|
|
|
ARMConstantPoolConstant *
|
|
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
|
|
ARMCP::ARMCPKind Kind, unsigned char PCAdj) {
|
|
return new ARMConstantPoolConstant(C, ID, Kind, PCAdj,
|
|
ARMCP::no_modifier, false);
|
|
}
|
|
|
|
ARMConstantPoolConstant *
|
|
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
|
|
ARMCP::ARMCPKind Kind, unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier Modifier,
|
|
bool AddCurrentAddress) {
|
|
return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier,
|
|
AddCurrentAddress);
|
|
}
|
|
|
|
const GlobalValue *ARMConstantPoolConstant::getGV() const {
|
|
return dyn_cast_or_null<GlobalValue>(CVal);
|
|
}
|
|
|
|
const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
|
|
return dyn_cast_or_null<BlockAddress>(CVal);
|
|
}
|
|
|
|
int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
|
|
unsigned Alignment) {
|
|
return getExistingMachineCPValueImpl<ARMConstantPoolConstant>(CP, Alignment);
|
|
}
|
|
|
|
bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
|
|
const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV);
|
|
return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV);
|
|
}
|
|
|
|
void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
|
ID.AddPointer(CVal);
|
|
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
|
|
}
|
|
|
|
void ARMConstantPoolConstant::print(raw_ostream &O) const {
|
|
O << CVal->getName();
|
|
ARMConstantPoolValue::print(O);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ARMConstantPoolSymbol
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, const char *s,
|
|
unsigned id,
|
|
unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier Modifier,
|
|
bool AddCurrentAddress)
|
|
: ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier,
|
|
AddCurrentAddress),
|
|
S(s) {}
|
|
|
|
ARMConstantPoolSymbol *
|
|
ARMConstantPoolSymbol::Create(LLVMContext &C, const char *s,
|
|
unsigned ID, unsigned char PCAdj) {
|
|
return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false);
|
|
}
|
|
|
|
int ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
|
|
unsigned Alignment) {
|
|
return getExistingMachineCPValueImpl<ARMConstantPoolSymbol>(CP, Alignment);
|
|
}
|
|
|
|
bool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) {
|
|
const ARMConstantPoolSymbol *ACPS = dyn_cast<ARMConstantPoolSymbol>(ACPV);
|
|
return ACPS && ACPS->S == S && ARMConstantPoolValue::hasSameValue(ACPV);
|
|
}
|
|
|
|
void ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
|
ID.AddString(S);
|
|
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
|
|
}
|
|
|
|
void ARMConstantPoolSymbol::print(raw_ostream &O) const {
|
|
O << S;
|
|
ARMConstantPoolValue::print(O);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ARMConstantPoolMBB
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C,
|
|
const MachineBasicBlock *mbb,
|
|
unsigned id, unsigned char PCAdj,
|
|
ARMCP::ARMCPModifier Modifier,
|
|
bool AddCurrentAddress)
|
|
: ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj,
|
|
Modifier, AddCurrentAddress),
|
|
MBB(mbb) {}
|
|
|
|
ARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C,
|
|
const MachineBasicBlock *mbb,
|
|
unsigned ID,
|
|
unsigned char PCAdj) {
|
|
return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false);
|
|
}
|
|
|
|
int ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP,
|
|
unsigned Alignment) {
|
|
return getExistingMachineCPValueImpl<ARMConstantPoolMBB>(CP, Alignment);
|
|
}
|
|
|
|
bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) {
|
|
const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(ACPV);
|
|
return ACPMBB && ACPMBB->MBB == MBB &&
|
|
ARMConstantPoolValue::hasSameValue(ACPV);
|
|
}
|
|
|
|
void ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
|
ID.AddPointer(MBB);
|
|
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
|
|
}
|
|
|
|
void ARMConstantPoolMBB::print(raw_ostream &O) const {
|
|
O << "BB#" << MBB->getNumber();
|
|
ARMConstantPoolValue::print(O);
|
|
}
|