TargetLoweringObjectFile.cpp [plain text]
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
void TargetLoweringObjectFile::Initialize(MCContext &ctx,
const TargetMachine &TM) {
Ctx = &ctx;
InitMCObjectFileInfo(TM.getTargetTriple(),
TM.getRelocationModel(), TM.getCodeModel(), *Ctx);
}
TargetLoweringObjectFile::~TargetLoweringObjectFile() {
}
static bool isSuitableForBSS(const GlobalVariable *GV, bool NoZerosInBSS) {
const Constant *C = GV->getInitializer();
if (!C->isNullValue())
return false;
if (GV->isConstant())
return false;
if (!GV->getSection().empty())
return false;
if (NoZerosInBSS)
return false;
return true;
}
static bool IsNullTerminatedString(const Constant *C) {
if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C)) {
unsigned NumElts = CDS->getNumElements();
assert(NumElts != 0 && "Can't have an empty CDS");
if (CDS->getElementAsInteger(NumElts-1) != 0)
return false;
for (unsigned i = 0; i != NumElts-1; ++i)
if (CDS->getElementAsInteger(i) == 0)
return false;
return true;
}
if (isa<ConstantAggregateZero>(C))
return cast<ArrayType>(C->getType())->getNumElements() == 1;
return false;
}
MCSymbol *TargetLoweringObjectFile::
getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI) const {
return Mang->getSymbol(GV);
}
void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,
const TargetMachine &TM,
const MCSymbol *Sym) const {
}
SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
const TargetMachine &TM){
assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
"Can only be used for global definitions");
Reloc::Model ReloModel = TM.getRelocationModel();
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
if (GVar == 0)
return SectionKind::getText();
if (GVar->isThreadLocal()) {
if (isSuitableForBSS(GVar, TM.Options.NoZerosInBSS))
return SectionKind::getThreadBSS();
return SectionKind::getThreadData();
}
if (GVar->hasCommonLinkage())
return SectionKind::getCommon();
if (isSuitableForBSS(GVar, TM.Options.NoZerosInBSS)) {
if (GVar->hasLocalLinkage())
return SectionKind::getBSSLocal();
else if (GVar->hasExternalLinkage())
return SectionKind::getBSSExtern();
return SectionKind::getBSS();
}
const Constant *C = GVar->getInitializer();
if (GVar->isConstant()) {
switch (C->getRelocationInfo()) {
case Constant::NoRelocation:
if (!GVar->hasUnnamedAddr())
return SectionKind::getReadOnly();
if (ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
if (IntegerType *ITy =
dyn_cast<IntegerType>(ATy->getElementType())) {
if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
ITy->getBitWidth() == 32) &&
IsNullTerminatedString(C)) {
if (ITy->getBitWidth() == 8)
return SectionKind::getMergeable1ByteCString();
if (ITy->getBitWidth() == 16)
return SectionKind::getMergeable2ByteCString();
assert(ITy->getBitWidth() == 32 && "Unknown width");
return SectionKind::getMergeable4ByteCString();
}
}
}
switch (TM.getTargetData()->getTypeAllocSize(C->getType())) {
case 4: return SectionKind::getMergeableConst4();
case 8: return SectionKind::getMergeableConst8();
case 16: return SectionKind::getMergeableConst16();
default: return SectionKind::getMergeableConst();
}
case Constant::LocalRelocation:
if (ReloModel == Reloc::Static)
return SectionKind::getReadOnly();
return SectionKind::getReadOnlyWithRelLocal();
case Constant::GlobalRelocations:
if (ReloModel == Reloc::Static)
return SectionKind::getReadOnly();
return SectionKind::getReadOnlyWithRel();
}
}
if (ReloModel == Reloc::Static)
return SectionKind::getDataNoRel();
switch (C->getRelocationInfo()) {
case Constant::NoRelocation:
return SectionKind::getDataNoRel();
case Constant::LocalRelocation:
return SectionKind::getDataRelLocal();
case Constant::GlobalRelocations:
return SectionKind::getDataRel();
}
llvm_unreachable("Invalid relocation");
}
const MCSection *TargetLoweringObjectFile::
SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang,
const TargetMachine &TM) const {
if (GV->hasSection())
return getExplicitSectionGlobal(GV, Kind, Mang, TM);
return SelectSectionForGlobal(GV, Kind, Mang, TM);
}
const MCSection *
TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
Mangler *Mang,
const TargetMachine &TM) const{
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
if (Kind.isText())
return getTextSection();
if (Kind.isBSS() && BSSSection != 0)
return BSSSection;
if (Kind.isReadOnly() && ReadOnlySection != 0)
return ReadOnlySection;
return getDataSection();
}
const MCSection *
TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
if (Kind.isReadOnly() && ReadOnlySection != 0)
return ReadOnlySection;
return DataSection;
}
const MCExpr *TargetLoweringObjectFile::
getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI, unsigned Encoding,
MCStreamer &Streamer) const {
const MCSymbol *Sym = Mang->getSymbol(GV);
return getExprForDwarfReference(Sym, Encoding, Streamer);
}
const MCExpr *TargetLoweringObjectFile::
getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding,
MCStreamer &Streamer) const {
const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext());
switch (Encoding & 0x70) {
default:
report_fatal_error("We do not support this DWARF encoding yet!");
case dwarf::DW_EH_PE_absptr:
return Res;
case dwarf::DW_EH_PE_pcrel: {
MCSymbol *PCSym = getContext().CreateTempSymbol();
Streamer.EmitLabel(PCSym);
const MCExpr *PC = MCSymbolRefExpr::Create(PCSym, getContext());
return MCBinaryExpr::CreateSub(Res, PC, getContext());
}
}
}