Rip all of the global variable lowering logic out of TargetAsmInfo. Since

it is highly specific to the object file that will be generated in the end,
this introduces a new TargetLoweringObjectFile interface that is implemented
for each of ELF/MachO/COFF/Alpha/PIC16 and XCore.

Though still is still a brutal and ugly refactoring, this is a major step
towards goodness.

This patch also:
1. fixes a bunch of dangling pointer problems in the PIC16 backend.
2. disables the TargetLowering copy ctor which PIC16 was accidentally using.
3. gets us closer to xcore having its own crazy target section flags and
   pic16 not having to shadow sections with its own objects.
4. fixes wierdness where ELF targets would set CStringSection but not
   CStringSection_.  Factor the code better.
5. fixes some bugs in string lowering on ELF targets.




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-07-28 03:13:23 +00:00
parent 7988aff079
commit f0144127b9
64 changed files with 1655 additions and 1402 deletions

View File

@ -39,6 +39,7 @@ namespace llvm {
class Mangler;
class Section;
class TargetAsmInfo;
class TargetLoweringObjectFile;
class Type;
class formatted_raw_ostream;
@ -75,6 +76,9 @@ namespace llvm {
///
TargetMachine &TM;
/// getObjFileLowering - Return information about object file lowering.
const TargetLoweringObjectFile &getObjFileLowering() const;
/// Target Asm Printer information.
///
const TargetAsmInfo *TAI;

View File

@ -16,15 +16,9 @@ namespace llvm {
class COFFTargetAsmInfo : public TargetAsmInfo {
protected:
explicit COFFTargetAsmInfo(const TargetMachine &TM);
public:
virtual void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const;
virtual const Section *
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind) const;
};
}
#endif // LLVM_ELF_TARGET_ASM_INFO_H
#endif // LLVM_COFF_TARGET_ASM_INFO_H

View File

@ -24,27 +24,9 @@ namespace llvm {
class Mangler;
struct DarwinTargetAsmInfo : public TargetAsmInfo {
const Section* TextCoalSection;
const Section* ConstTextCoalSection;
const Section* ConstDataCoalSection;
const Section* ConstDataSection;
const Section* DataCoalSection;
const Section* FourByteConstantSection;
const Section* EightByteConstantSection;
const Section* SixteenByteConstantSection;
explicit DarwinTargetAsmInfo(const TargetMachine &TM);
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const;
virtual bool emitUsedDirectiveFor(const GlobalValue *GV,
Mangler *Mang) const;
virtual const Section *
getSectionForMergeableConstant(SectionKind Kind) const;
private:
const Section* MergeableStringSection(const GlobalVariable *GV) const;
};
}

View File

@ -21,29 +21,6 @@ namespace llvm {
struct ELFTargetAsmInfo : public TargetAsmInfo {
ELFTargetAsmInfo(const TargetMachine &TM);
/// getSectionForMergeableConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
virtual const Section *
getSectionForMergeableConstant(SectionKind Kind) const;
virtual SectionKind::Kind getKindForNamedSection(const char *Section,
SectionKind::Kind K) const;
void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const;
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const;
const Section *DataRelSection;
const Section *DataRelLocalSection;
const Section *DataRelROSection;
const Section *DataRelROLocalSection;
const Section *MergeableConst4Section;
const Section *MergeableConst8Section;
const Section *MergeableConst16Section;
};
}

View File

@ -214,15 +214,12 @@ namespace llvm {
};
class Section {
friend class TargetAsmInfo;
friend class StringMapEntry<Section>;
friend class StringMap<Section>;
public:
std::string Name;
SectionKind Kind;
explicit Section() { }
public:
explicit Section() { }
const std::string &getName() const { return Name; }
SectionKind getKind() const { return Kind; }
};
@ -230,8 +227,6 @@ namespace llvm {
/// TargetAsmInfo - This class is intended to be used as a base class for asm
/// properties and features specific to the target.
class TargetAsmInfo {
private:
mutable StringMap<Section> Sections;
protected:
/// TM - The current TargetMachine.
const TargetMachine &TM;
@ -240,33 +235,11 @@ namespace llvm {
// Properties to be set by the target writer, used to configure asm printer.
//
/// TextSection - Section directive for standard text.
///
const Section *TextSection; // Defaults to ".text".
/// DataSection - Section directive for standard data.
///
const Section *DataSection; // Defaults to ".data".
/// BSSSection - Section directive for uninitialized data. Null if this
/// target doesn't support a BSS section.
///
/// FIXME: REMOVE.
const char *BSSSection; // Default to ".bss".
const Section *BSSSection_;
/// ReadOnlySection - This is the directive that is emitted to switch to a
/// read-only section for constant data (e.g. data declared const,
/// jump tables).
const Section *ReadOnlySection; // Defaults to NULL
/// TLSDataSection - Section directive for Thread Local data.
///
const Section *TLSDataSection; // Defaults to ".tdata".
/// TLSBSSSection - Section directive for Thread Local uninitialized data.
/// Null if this target doesn't support a BSS section.
///
const Section *TLSBSSSection; // Defaults to ".tbss".
/// ZeroFillDirective - Directive for emitting a global to the ZeroFill
/// section on this target. Null if this target doesn't support zerofill.
@ -456,8 +429,8 @@ namespace llvm {
/// cstring constants (null terminated string that does not contain any
/// other null bytes) on this target. This is commonly supported as
/// ".cstring".
/// FIXME: REMOVE.
const char *CStringSection; // Defaults to NULL
const Section *CStringSection_;
/// StaticCtorsSection - This is the directive that is emitted to switch to
/// a section to emit the static constructor list.
@ -642,10 +615,6 @@ namespace llvm {
explicit TargetAsmInfo(const TargetMachine &TM);
virtual ~TargetAsmInfo();
const Section *getOrCreateSection(const char *Name,
bool isDirective,
SectionKind::Kind K) const;
/// Measure the specified inline asm to determine an approximation of its
/// length.
virtual unsigned getInlineAsmLength(const char *Str) const;
@ -665,48 +634,6 @@ namespace llvm {
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
/// getSectionForMergeableConstant - Given a Mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
virtual const Section *getSectionForMergeableConstant(SectionKind Kind)const;
/// getKindForNamedSection - If this target wants to be able to override
/// section flags based on the name of the section specified for a global
/// variable, it can implement this. This is used on ELF systems so that
/// ".tbss" gets the TLS bit set etc.
virtual SectionKind::Kind getKindForNamedSection(const char *Section,
SectionKind::Kind K) const{
return K;
}
/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition. This should not
/// be passed external (or available externally) globals.
// FIXME: MOVE TO ASMPRINTER.
const Section* SectionForGlobal(const GlobalValue *GV) const;
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
/// FIXME: ELIMINATE this by making PIC16 implement ADDRESS with
/// getFlagsForNamedSection.
virtual const Section *
getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const {
return 0;
}
/// getSectionFlagsAsString - Turn the flags in the specified SectionKind
/// into a string that can be printed to the assembly file after the
/// ".section foo" part of a section directive.
virtual void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
}
// FIXME: Eliminate this.
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const;
/// getSLEB128Size - Compute the number of bytes required for a signed
/// leb128 value.
@ -734,27 +661,9 @@ namespace llvm {
// Accessors.
//
const Section *getTextSection() const {
return TextSection;
}
const Section *getDataSection() const {
return DataSection;
}
const char *getBSSSection() const {
return BSSSection;
}
const Section *getBSSSection_() const {
return BSSSection_;
}
const Section *getReadOnlySection() const {
return ReadOnlySection;
}
const Section *getTLSDataSection() const {
return TLSDataSection;
}
const Section *getTLSBSSSection() const {
return TLSBSSSection;
}
const char *getZeroFillDirective() const {
return ZeroFillDirective;
}
@ -869,9 +778,6 @@ namespace llvm {
const char *getCStringSection() const {
return CStringSection;
}
const Section *getCStringSection_() const {
return CStringSection_;
}
const char *getStaticCtorsSection() const {
return StaticCtorsSection;
}

View File

@ -54,6 +54,7 @@ namespace llvm {
class TargetMachine;
class TargetRegisterClass;
class TargetSubtarget;
class TargetLoweringObjectFile;
class Value;
// FIXME: should this be here?
@ -77,6 +78,8 @@ namespace llvm {
/// target-specific constructs to SelectionDAG operators.
///
class TargetLowering {
TargetLowering(const TargetLowering&); // DO NOT IMPLEMENT
void operator=(const TargetLowering&); // DO NOT IMPLEMENT
public:
/// LegalizeAction - This enum indicates whether operations are valid for a
/// target, and if not, what action should be used to make them valid.
@ -98,11 +101,13 @@ public:
SchedulingForRegPressure // Scheduling for lowest register pressure.
};
explicit TargetLowering(TargetMachine &TM);
/// NOTE: The constructor takes ownership of TLOF.
explicit TargetLowering(TargetMachine &TM, TargetLoweringObjectFile *TLOF);
virtual ~TargetLowering();
TargetMachine &getTargetMachine() const { return TM; }
const TargetData *getTargetData() const { return TD; }
const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; }
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
@ -1475,6 +1480,7 @@ public:
private:
TargetMachine &TM;
const TargetData *TD;
TargetLoweringObjectFile &TLOF;
/// PointerTy - The type to use for pointers, usually i32 or i64.
///

View File

@ -0,0 +1,187 @@
//===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements classes used to handle lowerings specific to common
// object file formats.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
// FIXME: Switch to MC.
#include "llvm/Target/TargetAsmInfo.h"
namespace llvm {
class TargetLoweringObjectFile {
private:
mutable StringMap<Section> Sections;
protected:
TargetLoweringObjectFile();
/// TextSection - Section directive for standard text.
///
const Section *TextSection; // Defaults to ".text".
/// DataSection - Section directive for standard data.
///
const Section *DataSection; // Defaults to ".data".
// FIXME: SINK THESE.
const Section *BSSSection_;
/// ReadOnlySection - This is the directive that is emitted to switch to a
/// read-only section for constant data (e.g. data declared const,
/// jump tables).
const Section *ReadOnlySection; // Defaults to NULL
/// TLSDataSection - Section directive for Thread Local data.
///
const Section *TLSDataSection; // Defaults to ".tdata".
/// TLSBSSSection - Section directive for Thread Local uninitialized data.
/// Null if this target doesn't support a BSS section.
///
const Section *TLSBSSSection; // Defaults to ".tbss".
const Section *CStringSection_;
public:
// FIXME: NONPUB.
const Section *getOrCreateSection(const char *Name,
bool isDirective,
SectionKind::Kind K) const;
public:
virtual ~TargetLoweringObjectFile();
const Section *getTextSection() const { return TextSection; }
const Section *getDataSection() const { return DataSection; }
/// getSectionForMergeableConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
virtual const Section *
getSectionForMergeableConstant(SectionKind Kind) const;
/// getKindForNamedSection - If this target wants to be able to override
/// section flags based on the name of the section specified for a global
/// variable, it can implement this. This is used on ELF systems so that
/// ".tbss" gets the TLS bit set etc.
virtual SectionKind::Kind getKindForNamedSection(const char *Section,
SectionKind::Kind K) const{
return K;
}
/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition. This should not
/// be passed external (or available externally) globals.
const Section *SectionForGlobal(const GlobalValue *GV,
const TargetMachine &TM) const;
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
/// FIXME: ELIMINATE this by making PIC16 implement ADDRESS with
/// getFlagsForNamedSection.
virtual const Section *
getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const {
return 0;
}
/// getSectionFlagsAsString - Turn the flags in the specified SectionKind
/// into a string that can be printed to the assembly file after the
/// ".section foo" part of a section directive.
virtual void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
}
protected:
virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
const TargetMachine &TM) const;
};
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
bool AtIsCommentChar; // True if @ is the comment character on this target.
public:
/// ELF Constructor - AtIsCommentChar is true if the CommentCharacter from TAI
/// is "@".
TargetLoweringObjectFileELF(bool AtIsCommentChar = false,
// FIXME: REMOVE AFTER UNIQUING IS FIXED.
bool HasCrazyBSS = false);
/// getSectionForMergeableConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
virtual const Section *
getSectionForMergeableConstant(SectionKind Kind) const;
virtual SectionKind::Kind getKindForNamedSection(const char *Section,
SectionKind::Kind K) const;
void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const;
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
const TargetMachine &TM) const;
protected:
const Section *DataRelSection;
const Section *DataRelLocalSection;
const Section *DataRelROSection;
const Section *DataRelROLocalSection;
const Section *MergeableConst4Section;
const Section *MergeableConst8Section;
const Section *MergeableConst16Section;
};
class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
const Section *TextCoalSection;
const Section *ConstTextCoalSection;
const Section *ConstDataCoalSection;
const Section *ConstDataSection;
const Section *DataCoalSection;
const Section *FourByteConstantSection;
const Section *EightByteConstantSection;
const Section *SixteenByteConstantSection;
public:
TargetLoweringObjectFileMachO();
virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
const TargetMachine &TM) const;
virtual const Section *
getSectionForMergeableConstant(SectionKind Kind) const;
};
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
public:
TargetLoweringObjectFileCOFF();
virtual void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const;
virtual const Section *
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
const TargetMachine &TM) const;
};
} // end namespace llvm
#endif

View File

@ -32,6 +32,7 @@
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -72,6 +73,11 @@ AsmPrinter::~AsmPrinter() {
delete &OutContext;
}
const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
return TM.getTargetLowering()->getObjFileLowering();
}
/// SwitchToTextSection - Switch to the specified text section of the executable
/// if we are not already in it!
///
@ -146,7 +152,8 @@ void AsmPrinter::SwitchToSection(const Section *NS) {
// some magic assembler directive.
if (NS->getKind().hasExplicitSection()) {
SmallString<32> FlagsStr;
TAI->getSectionFlagsAsString(NS->getKind(), FlagsStr);
getObjFileLowering().getSectionFlagsAsString(NS->getKind(), FlagsStr);
O << TAI->getSwitchToSectionDirective()
<< CurrentSection
@ -240,9 +247,6 @@ bool AsmPrinter::doFinalization(Module &M) {
}
if (TAI->getSetDirective()) {
if (!M.alias_empty())
SwitchToSection(TAI->getTextSection());
O << '\n';
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) {
@ -339,7 +343,7 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
}
}
const Section *S = TAI->getSectionForMergeableConstant(Kind);
const Section *S =getObjFileLowering().getSectionForMergeableConstant(Kind);
// The number of sections are small, just do a linear search from the
// last section to the first.
@ -410,8 +414,9 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
const char* JumpTableDataSection = TAI->getJumpTableDataSection();
const Function *F = MF.getFunction();
const Section *FuncSection = TAI->SectionForGlobal(F);
const Section *FuncSection = getObjFileLowering().SectionForGlobal(F, TM);
bool JTInDiffSection = false;
if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) ||
!JumpTableDataSection ||

View File

@ -17,9 +17,10 @@
#include "llvm/Support/Timer.h"
#include "llvm/System/Path.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
static TimerGroup &getDwarfTimerGroup() {
@ -1328,7 +1329,7 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) {
MMI->setDebugInfoAvailability(true);
// Prime section data.
SectionMap.insert(TAI->getTextSection());
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
// Print out .file directives to specify files for .loc directives. These are
// printed out early so that they precede any .loc directives.
@ -1363,9 +1364,9 @@ void DwarfDebug::EndModule() {
DebugTimer->startTimer();
// Standard sections final addresses.
Asm->SwitchToSection(TAI->getTextSection());
Asm->SwitchToSection(Asm->getObjFileLowering().getTextSection());
EmitLabel("text_end", 0);
Asm->SwitchToSection(TAI->getDataSection());
Asm->SwitchToSection(Asm->getObjFileLowering().getDataSection());
EmitLabel("data_end", 0);
// End text sections.
@ -1893,9 +1894,9 @@ void DwarfDebug::EmitInitial() {
Asm->SwitchToDataSection(TAI->getDwarfRangesSection());
EmitLabel("section_ranges", 0);
Asm->SwitchToSection(TAI->getTextSection());
Asm->SwitchToSection(Asm->getObjFileLowering().getTextSection());
EmitLabel("text_begin", 0);
Asm->SwitchToSection(TAI->getDataSection());
Asm->SwitchToSection(Asm->getObjFileLowering().getDataSection());
EmitLabel("data_begin", 0);
}

View File

@ -20,8 +20,8 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
namespace {
@ -64,10 +64,10 @@ static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP,
void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI) {
AP.SwitchToSection(TAI.getTextSection());
AP.SwitchToSection(AP.getObjFileLowering().getTextSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin");
AP.SwitchToSection(TAI.getDataSection());
AP.SwitchToSection(AP.getObjFileLowering().getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin");
}
@ -99,16 +99,16 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
AddressAlignLog = 3;
}
AP.SwitchToSection(TAI.getTextSection());
AP.SwitchToSection(AP.getObjFileLowering().getTextSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end");
AP.SwitchToSection(TAI.getDataSection());
AP.SwitchToSection(AP.getObjFileLowering().getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end");
OS << AddressDirective << 0; // FIXME: Why does ocaml emit this??
AP.EOL();
AP.SwitchToSection(TAI.getDataSection());
AP.SwitchToSection(AP.getObjFileLowering().getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable");
for (iterator I = begin(), IE = end(); I != IE; ++I) {

View File

@ -45,6 +45,8 @@
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/Streams.h"
@ -185,7 +187,10 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
}
}
return getSection(TAI->getSectionForMergeableConstant(Kind)->getName(),
const TargetLoweringObjectFile &TLOF =
TM.getTargetLowering()->getObjFileLowering();
return getSection(TLOF.getSectionForMergeableConstant(Kind)->getName(),
ELFSection::SHT_PROGBITS,
ELFSection::SHF_MERGE | ELFSection::SHF_ALLOC,
CPE.getAlignment());
@ -312,8 +317,11 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
assert(isa<GlobalVariable>(GV) && "GV not a global variable!");
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
const TargetLoweringObjectFile &TLOF =
TM.getTargetLowering()->getObjFileLowering();
// Get ELF section from TAI
const Section *S = TAI->SectionForGlobal(GV);
const Section *S = TLOF.SectionForGlobal(GV, TM);
unsigned SectionFlags = getElfSectionFlags(S->getKind());
// The symbol align should update the section alignment if needed

View File

@ -11,12 +11,13 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtarget.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtarget.h"
#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@ -440,8 +441,9 @@ static void InitCmpLibcallCCs(ISD::CondCode *CCs) {
CCs[RTLIB::O_F64] = ISD::SETEQ;
}
TargetLowering::TargetLowering(TargetMachine &tm)
: TM(tm), TD(TM.getTargetData()) {
/// NOTE: The constructor takes ownership of TLOF.
TargetLowering::TargetLowering(TargetMachine &tm,TargetLoweringObjectFile *tlof)
: TM(tm), TD(TM.getTargetData()), TLOF(*tlof) {
// All operations default to being supported.
memset(OpActions, 0, sizeof(OpActions));
memset(LoadExtActions, 0, sizeof(LoadExtActions));
@ -522,7 +524,9 @@ TargetLowering::TargetLowering(TargetMachine &tm)
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
}
TargetLowering::~TargetLowering() {}
TargetLowering::~TargetLowering() {
delete &TLOF;
}
/// computeRegisterProperties - Once all of the register classes are added,
/// this allows us to compute derived properties we expose.

View File

@ -34,6 +34,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Support/ErrorHandling.h"
@ -103,8 +104,14 @@ void ARMTargetLowering::addQRTypeForNEON(MVT VT) {
addTypeForNEON(VT, MVT::v2f64, MVT::v4i32);
}
static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) {
if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin())
return new TargetLoweringObjectFileMachO();
return new TargetLoweringObjectFileELF(true);
}
ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
: TargetLowering(TM), ARMPCLabelIndex(0) {
: TargetLowering(TM, createTLOF(TM)), ARMPCLabelIndex(0) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
if (Subtarget->isTargetDarwin()) {

View File

@ -59,8 +59,6 @@ ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM):
ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
NeedsSet = false;
HasLEB128 = true;
AbsoluteDebugSectionOffsets = true;

View File

@ -29,6 +29,7 @@
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
@ -1127,7 +1128,7 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
if (Subtarget->isTargetELF())
O << "\t.type " << name << ",%object\n";
const Section *TheSection = TAI->SectionForGlobal(GVar);
const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM);
SwitchToSection(TheSection);
// FIXME: get this stuff from section kind flags.
@ -1154,7 +1155,7 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
O << TAI->getCOMMDirective() << name << "," << Size
<< ',' << Align;
} else {
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
O << "\t.globl " << name << '\n'
<< TAI->getWeakDefDirective() << name << '\n';
EmitAlignment(Align, GVar);
@ -1285,7 +1286,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
}
if (!HiddenGVNonLazyPtrs.empty()) {
SwitchToSection(TAI->getDataSection());
SwitchToSection(getObjFileLowering().getDataSection());
for (StringMap<std::string>::iterator I = HiddenGVNonLazyPtrs.begin(),
E = HiddenGVNonLazyPtrs.end(); I != E; ++I) {
EmitAlignment(2);

View File

@ -21,6 +21,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
@ -30,6 +31,17 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
class TargetLoweringObjectFileAlpha : public TargetLoweringObjectFile {
public:
TargetLoweringObjectFileAlpha() {
TextSection = getOrCreateSection("_text", true, SectionKind::Text);
DataSection = getOrCreateSection("_data", true, SectionKind::DataRel);
}
};
/// AddLiveIn - This helper function adds the specified physical register to the
/// MachineFunction as a live in value. It also creates a corresponding virtual
/// register for it.
@ -41,7 +53,8 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
return VReg;
}
AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileAlpha()) {
// Set up the TargetLowering object.
//I am having problems with shr n i8 1
setShiftAmountType(MVT::i64);

View File

@ -23,7 +23,4 @@ AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM)
JumpTableDirective = ".gprel32";
JumpTableDataSection = "\t.section .rodata\n";
WeakRefDirective = "\t.weak\t";
TextSection = getOrCreateSection("_text", true, SectionKind::Text);
DataSection = getOrCreateSection("_data", true, SectionKind::DataRel);
}

View File

@ -23,6 +23,7 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Compiler.h"
@ -138,7 +139,7 @@ bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Print out labels for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
EmitAlignment(MF.getAlignment(), F);
switch (F->getLinkage()) {
@ -214,7 +215,7 @@ void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
unsigned Align = TD->getPreferredAlignmentLog(GVar);
// 0: Switch to section
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
// 1: Check visibility
printVisibility(name, GVar->getVisibility());

View File

@ -10,6 +10,7 @@ add_llvm_library(LLVMTarget
TargetFrameInfo.cpp
TargetInstrInfo.cpp
TargetIntrinsicInfo.cpp
TargetLoweringObjectFile.cpp
TargetMachOWriterInfo.cpp
TargetMachine.cpp
TargetRegisterInfo.cpp

View File

@ -19,9 +19,6 @@ using namespace llvm;
COFFTargetAsmInfo::COFFTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) {
TextSection = getOrCreateSection("_text", true, SectionKind::Text);
DataSection = getOrCreateSection("_data", true, SectionKind::DataRel);
GlobalPrefix = "_";
LCOMMDirective = "\t.lcomm\t";
COMMDirectiveTakesAlignment = false;
@ -53,57 +50,3 @@ COFFTargetAsmInfo::COFFTargetAsmInfo(const TargetMachine &TM)
DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
}
void COFFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
// FIXME: Inefficient.
std::string Res = ",\"";
if (Kind.isText())
Res += 'x';
if (Kind.isWriteable())
Res += 'w';
Res += "\"";
Str.append(Res.begin(), Res.end());
}
//===----------------------------------------------------------------------===//
// Move to AsmPrinter (mangler access).
//===----------------------------------------------------------------------===//
#include "llvm/GlobalVariable.h"
static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText())
return ".text$linkonce";
if (Kind.isWriteable())
return ".data$linkonce";
return ".rdata$linkonce";
}
const Section *
COFFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const {
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
// If this global is linkonce/weak and the target handles this by emitting it
// into a 'uniqued' section name, create and return the section now.
if (Kind.isWeak()) {
const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
// FIXME: Use mangler interface (PR4584).
std::string Name = Prefix+GV->getNameStr();
return getOrCreateSection(Name.c_str(), false, Kind.getKind());
}
if (Kind.isText())
return getTextSection();
if (Kind.isBSS())
if (const Section *S = getBSSSection_())
return S;
if (Kind.isReadOnly())
if (const Section *S = getReadOnlySection())
return S;
return getDataSection();
}

View File

@ -34,9 +34,10 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
@ -427,7 +428,7 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
// Print out labels for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
EmitAlignment(MF.getAlignment(), F);
switch (F->getLinkage()) {
@ -525,7 +526,7 @@ void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
if (C->isNullValue() && /* FIXME: Verify correct */
!GVar->hasSection() &&

View File

@ -15,8 +15,9 @@
#include "SPUISelLowering.h"
#include "SPUTargetMachine.h"
#include "SPUFrameInfo.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@ -24,15 +25,13 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
#include <map>
using namespace llvm;
@ -125,9 +124,8 @@ namespace {
}
SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
: TargetLowering(TM),
SPUTM(TM)
{
: TargetLowering(TM, new TargetLoweringObjectFileELF()),
SPUTM(TM) {
// Fold away setcc operations if possible.
setPow2DivIsCheap();

View File

@ -33,10 +33,6 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
HasLEB128 = true;
HasDotLocAndDotFile = true;
// BSS section needs to be emitted as ".section"
BSSSection = "\t.section\t.bss";
BSSSection_ = getOrCreateSection("\t.bss", false, SectionKind::BSS);
SupportsDebugInformation = true;
NeedsSet = true;
DwarfAbbrevSection = "\t.section .debug_abbrev,\"\",@progbits";

View File

@ -27,32 +27,7 @@ using namespace llvm;
DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) {
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel);
CStringSection_ = getOrCreateSection("\t.cstring", true,
SectionKind::MergeableCString);
FourByteConstantSection = getOrCreateSection("\t.literal4\n", true,
SectionKind::MergeableConst4);
EightByteConstantSection = getOrCreateSection("\t.literal8\n", true,
SectionKind::MergeableConst8);
SixteenByteConstantSection =
getOrCreateSection("\t.literal16\n", true, SectionKind::MergeableConst16);
ReadOnlySection = getOrCreateSection("\t.const", true, SectionKind::ReadOnly);
TextCoalSection =
getOrCreateSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions",
false, SectionKind::Text);
ConstTextCoalSection = getOrCreateSection("\t__TEXT,__const_coal,coalesced",
false, SectionKind::Text);
ConstDataCoalSection = getOrCreateSection("\t__DATA,__const_coal,coalesced",
false, SectionKind::Text);
ConstDataSection = getOrCreateSection("\t.const_data", true,
SectionKind::ReadOnlyWithRel);
DataCoalSection = getOrCreateSection("\t__DATA,__datacoal_nt,coalesced",
false, SectionKind::DataRel);
// Common settings for all Darwin targets.
// Syntax:
GlobalPrefix = "_";
@ -124,79 +99,3 @@ bool DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
return true;
}
const Section*
DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const {
assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS");
if (Kind.isText())
return Kind.isWeak() ? TextCoalSection : TextSection;
// If this is weak/linkonce, put this in a coalescable section, either in text
// or data depending on if it is writable.
if (Kind.isWeak()) {
if (Kind.isReadOnly())
return ConstTextCoalSection;
return DataCoalSection;
}
// FIXME: Alignment check should be handled by section classifier.
if (Kind.isMergeableCString())
return MergeableStringSection(cast<GlobalVariable>(GV));
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
return SixteenByteConstantSection;
return ReadOnlySection; // .const
}
// FIXME: ROData -> const in -static mode that is relocatable but they happen
// by the static linker. Why not mergeable?
if (Kind.isReadOnly())
return getReadOnlySection();
// If this is marked const, put it into a const section. But if the dynamic
// linker needs to write to it, put it in the data segment.
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
// Otherwise, just drop the variable in the normal data section.
return DataSection;
}
const Section*
DarwinTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
const TargetData *TD = TM.getTargetData();
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size) {
unsigned Align = TD->getPreferredAlignment(GV);
if (Align <= 32)
return getCStringSection_();
}
return getReadOnlySection();
}
const Section *
DarwinTargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const {
// If this constant requires a relocation, we have to put it in the data
// segment, not in the text segment.
if (Kind.isDataRel())
return ConstDataSection;
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
return SixteenByteConstantSection;
return ReadOnlySection; // .const
}

View File

@ -18,217 +18,4 @@ using namespace llvm;
ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) {
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel);
ReadOnlySection =
getOrCreateSection("\t.rodata", false, SectionKind::ReadOnly);
TLSDataSection =
getOrCreateSection("\t.tdata", false, SectionKind::ThreadData);
TLSBSSSection = getOrCreateSection("\t.tbss", false, SectionKind::ThreadBSS);
DataRelSection = getOrCreateSection("\t.data.rel", false,
SectionKind::DataRel);
DataRelLocalSection = getOrCreateSection("\t.data.rel.local", false,
SectionKind::DataRelLocal);
DataRelROSection = getOrCreateSection("\t.data.rel.ro", false,
SectionKind::ReadOnlyWithRel);
DataRelROLocalSection =
getOrCreateSection("\t.data.rel.ro.local", false,
SectionKind::ReadOnlyWithRelLocal);
MergeableConst4Section = getOrCreateSection(".rodata.cst4", false,
SectionKind::MergeableConst4);
MergeableConst8Section = getOrCreateSection(".rodata.cst8", false,
SectionKind::MergeableConst8);
MergeableConst16Section = getOrCreateSection(".rodata.cst16", false,
SectionKind::MergeableConst16);
}
/// getFlagsForNamedSection - If this target wants to be able to infer
/// section flags based on the name of the section specified for a global
/// variable, it can implement this.
SectionKind::Kind ELFTargetAsmInfo::getKindForNamedSection(const char *Name,
SectionKind::Kind K) const {
if (Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
return SectionKind::BSS;
if (strcmp(Name, ".tdata") == 0 ||
strncmp(Name, ".tdata.", 7) == 0 ||
strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
return SectionKind::ThreadData;
if (strcmp(Name, ".tbss") == 0 ||
strncmp(Name, ".tbss.", 6) == 0 ||
strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
return SectionKind::ThreadBSS;
return K;
}
void ELFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
Str.push_back(',');
Str.push_back('"');
if (!Kind.isMetadata())
Str.push_back('a');
if (Kind.isText())
Str.push_back('x');
if (Kind.isWriteable())
Str.push_back('w');
if (Kind.isMergeableConst() || Kind.isMergeableCString())
Str.push_back('M');
if (Kind.isMergeableCString())
Str.push_back('S');
if (Kind.isThreadLocal())
Str.push_back('T');
Str.push_back('"');
Str.push_back(',');
// If comment string is '@', e.g. as on ARM - use '%' instead
if (strcmp(CommentString, "@") == 0)
Str.push_back('%');
else
Str.push_back('@');
const char *KindStr;
if (Kind.isBSS())
KindStr = "nobits";
else
KindStr = "progbits";
Str.append(KindStr, KindStr+strlen(KindStr));
if (Kind.isMergeableCString()) {
// TODO: Eventually handle multiple byte character strings. For now, all
// mergable C strings are single byte.
Str.push_back(',');
Str.push_back('1');
} else if (Kind.isMergeableConst4()) {
Str.push_back(',');
Str.push_back('4');
} else if (Kind.isMergeableConst8()) {
Str.push_back(',');
Str.push_back('8');
} else if (Kind.isMergeableConst16()) {
Str.push_back(',');
Str.push_back('1');
Str.push_back('6');
}
}
//===----------------------------------------------------------------------===//
// Move to AsmPrinter (mangler access).
//===----------------------------------------------------------------------===//
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringExtras.h"
static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText()) return ".gnu.linkonce.t.";
if (Kind.isReadOnly()) return ".gnu.linkonce.r.";
if (Kind.isThreadData()) return ".gnu.linkonce.td.";
if (Kind.isThreadBSS()) return ".gnu.linkonce.tb.";
if (Kind.isBSS()) return ".gnu.linkonce.b.";
if (Kind.isDataNoRel()) return ".gnu.linkonce.d.";
if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local.";
if (Kind.isDataRel()) return ".gnu.linkonce.d.rel.";
if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local.";
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return ".gnu.linkonce.d.rel.ro.";
}
const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const {
// If this global is linkonce/weak and the target handles this by emitting it
// into a 'uniqued' section name, create and return the section now.
if (Kind.isWeak()) {
const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
// FIXME: Use mangler interface (PR4584).
std::string Name = Prefix+GV->getNameStr();
return getOrCreateSection(Name.c_str(), false, Kind.getKind());
}
if (Kind.isText()) return TextSection;
if (Kind.isMergeableCString()) {
const TargetData *TD = TM.getTargetData();
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size <= 16) {
assert(getCStringSection() && "Should have string section prefix");
// We also need alignment here.
// FIXME: this is getting the alignment of the character, not the
// alignment of the string!!
unsigned Align = TD->getPrefTypeAlignment(Ty);
if (Align < Size)
Align = Size;
std::string Name = getCStringSection() + utostr(Size) + '.' +
utostr(Align);
return getOrCreateSection(Name.c_str(), false,
SectionKind::MergeableCString);
}
return getReadOnlySection();
}
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return MergeableConst4Section;
if (Kind.isMergeableConst8())
return MergeableConst8Section;
if (Kind.isMergeableConst16())
return MergeableConst16Section;
return ReadOnlySection; // .const
}
if (Kind.isReadOnly()) return getReadOnlySection();
if (Kind.isThreadData()) return TLSDataSection;
if (Kind.isThreadBSS()) return TLSBSSSection;
if (Kind.isBSS()) return getBSSSection_();
if (Kind.isDataNoRel()) return DataSection;
if (Kind.isDataRelLocal()) return DataRelLocalSection;
if (Kind.isDataRel()) return DataRelSection;
if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return DataRelROSection;
}
/// getSectionForMergeableConstant - Given a Mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
ELFTargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const {
return SelectSectionForGlobal(0, Kind);
}

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
@ -77,7 +78,7 @@ namespace {
void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
unsigned FnAlign = MF.getAlignment();
EmitAlignment(FnAlign, F);

View File

@ -31,13 +31,15 @@
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/VectorExtras.h"
using namespace llvm;
MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
TargetLowering(tm), Subtarget(*tm.getSubtargetImpl()), TM(tm) {
TargetLowering(tm, new TargetLoweringObjectFileELF()),
Subtarget(*tm.getSubtargetImpl()), TM(tm) {
// Set up the register classes.
addRegisterClass(MVT::i8, MSP430::GR8RegisterClass);

View File

@ -17,6 +17,4 @@ using namespace llvm;
MSP430TargetAsmInfo::MSP430TargetAsmInfo(const TargetMachine &TM)
: ELFTargetAsmInfo(TM) {
AlignmentIsInBytes = false;
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
}

View File

@ -31,6 +31,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
@ -211,12 +212,10 @@ emitCurrentABIString(void)
}
/// Emit the directives used by GAS on the start of functions
void MipsAsmPrinter::
emitFunctionStart(MachineFunction &MF)
{
void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) {
// Print out the label for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
// 2 bits aligned
EmitAlignment(MF.getAlignment(), F);
@ -485,7 +484,7 @@ void MipsAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
printVisibility(name, GVar->getVisibility());
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
if (C->isNullValue() && !GVar->hasSection()) {
if (!GVar->isThreadLocal() &&

View File

@ -30,15 +30,13 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
const char *MipsTargetLowering::
getTargetNodeName(unsigned Opcode) const
{
switch (Opcode)
{
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case MipsISD::JmpLink : return "MipsISD::JmpLink";
case MipsISD::Hi : return "MipsISD::Hi";
case MipsISD::Lo : return "MipsISD::Lo";
@ -55,8 +53,8 @@ getTargetNodeName(unsigned Opcode) const
}
MipsTargetLowering::
MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
{
MipsTargetLowering(MipsTargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
// Mips does not have i1 type, so use i32 for

View File

@ -30,8 +30,6 @@ MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM)
BSSSection = "\t.section\t.bss";
CStringSection = ".rodata.str";
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
if (!TM.getSubtarget<MipsSubtarget>().hasABICall())
JumpTableDirective = "\t.word\t";
else

View File

@ -21,4 +21,5 @@ add_llvm_target(PIC16
PIC16Subtarget.cpp
PIC16TargetAsmInfo.cpp
PIC16TargetMachine.cpp
PIC16TargetObjectFile.cpp
)

View File

@ -25,11 +25,20 @@
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;
#include "PIC16GenAsmWriter.inc"
PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
PTLI = static_cast<const PIC16TargetLowering*>(TM.getTargetLowering());
PTAI = static_cast<const PIC16TargetAsmInfo*>(T);
PTOF = static_cast<const PIC16TargetObjectFile*>(&PTLI->getObjFileLowering());
}
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
printInstruction(MI);
return true;
@ -59,10 +68,12 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
EmitAutos(CurrentFnName);
// Now emit the instructions of function in its code section.
const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
std::string T = PAN::getCodeSectionName(CurrentFnName);
const char *codeSection = T.c_str();
const Section *fCodeSection =
TAI->getOrCreateSection(codeSection, false, SectionKind::Text);
getObjFileLowering().getOrCreateSection(codeSection, false,
SectionKind::Text);
// Start the Code Section.
O << "\n";
SwitchToSection(fCodeSection);
@ -211,9 +222,8 @@ bool PIC16AsmPrinter::doInitialization(Module &M) {
// Set the section names for all globals.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
I->setSection(TAI->SectionForGlobal(I)->getName());
}
I != E; ++I)
I->setSection(getObjFileLowering().SectionForGlobal(I, TM)->getName());
DbgInfo.BeginModule(M);
EmitFunctionDecls(M);
@ -256,7 +266,7 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
// Emit variables imported from other Modules.
void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDecls->Items;
std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDecls->Items;
if (!Items.size()) return;
O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
@ -268,7 +278,7 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
// Emit variables defined in this module and are available to other modules.
void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDefs->Items;
std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDefs->Items;
if (!Items.size()) return;
O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
@ -281,12 +291,12 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
// Emit initialized data placed in ROM.
void PIC16AsmPrinter::EmitRomData(Module &M) {
// Print ROM Data section.
const std::vector<PIC16Section*> &ROSections = PTAI->ROSections;
const std::vector<PIC16Section*> &ROSections = PTOF->ROSections;
for (unsigned i = 0; i < ROSections.size(); i++) {
const std::vector<const GlobalVariable*> &Items = ROSections[i]->Items;
if (!Items.size()) continue;
O << "\n";
SwitchToSection(PTAI->ROSections[i]->S_);
SwitchToSection(PTOF->ROSections[i]->S_);
for (unsigned j = 0; j < Items.size(); j++) {
O << Mang->getMangledName(Items[j]);
Constant *C = Items[j]->getInitializer();
@ -310,10 +320,12 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
const TargetData *TD = TM.getTargetData();
// Emit the data section name.
O << "\n";
const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
std::string T = PAN::getFrameSectionName(CurrentFnName);
const char *SectionName = T.c_str();
const Section *fPDataSection =
TAI->getOrCreateSection(SectionName, false, SectionKind::DataRel);
getObjFileLowering().getOrCreateSection(SectionName, false,
SectionKind::DataRel);
SwitchToSection(fPDataSection);
// Emit function frame label
@ -352,7 +364,7 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
void PIC16AsmPrinter::EmitIData(Module &M) {
// Print all IDATA sections.
const std::vector<PIC16Section*> &IDATASections = PTAI->IDATASections;
const std::vector<PIC16Section*> &IDATASections = PTOF->IDATASections;
for (unsigned i = 0; i < IDATASections.size(); i++) {
O << "\n";
if (IDATASections[i]->S_->getName().find("llvm.") != std::string::npos)
@ -373,7 +385,7 @@ void PIC16AsmPrinter::EmitUData(Module &M) {
const TargetData *TD = TM.getTargetData();
// Print all BSS sections.
const std::vector<PIC16Section*> &BSSSections = PTAI->BSSSections;
const std::vector<PIC16Section*> &BSSSections = PTOF->BSSSections;
for (unsigned i = 0; i < BSSSections.size(); i++) {
O << "\n";
SwitchToSection(BSSSections[i]->S_);
@ -395,7 +407,7 @@ void PIC16AsmPrinter::EmitAutos(std::string FunctName) {
// Now print Autos section for this function.
std::string SectionName = PAN::getAutosSectionName(FunctName);
const std::vector<PIC16Section*> &AutosSections = PTAI->AutosSections;
const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections;
for (unsigned i = 0; i < AutosSections.size(); i++) {
O << "\n";
if (AutosSections[i]->S_->getName() == SectionName) {
@ -422,7 +434,7 @@ void PIC16AsmPrinter::EmitRemainingAutos() {
const TargetData *TD = TM.getTargetData();
// Now print Autos section for this function.
std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
std::vector <PIC16Section *>AutosSections = PTOF->AutosSections;
for (unsigned i = 0; i < AutosSections.size(); i++) {
// if the section is already printed then don't print again

View File

@ -18,6 +18,7 @@
#include "PIC16.h"
#include "PIC16TargetMachine.h"
#include "PIC16DebugInfo.h"
#include "PIC16TargetObjectFile.h"
#include "llvm/Analysis/DebugInfo.h"
#include "PIC16TargetAsmInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
@ -28,13 +29,10 @@
#include <string>
namespace llvm {
struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
class VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
public:
explicit PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
PTLI = static_cast<const PIC16TargetLowering *> (TM.getTargetLowering());
PTAI = static_cast<const PIC16TargetAsmInfo *> (T);
}
const TargetAsmInfo *T, bool V);
private:
virtual const char *getPassName() const {
return "PIC16 Assembly Printer";
@ -66,6 +64,7 @@ namespace llvm {
}
private:
PIC16TargetObjectFile *PTOF;
PIC16TargetLowering *PTLI;
PIC16DbgInfo DbgInfo;
const PIC16TargetAsmInfo *PTAI;

View File

@ -12,8 +12,8 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pic16-lower"
#include "PIC16ISelLowering.h"
#include "PIC16TargetObjectFile.h"
#include "PIC16TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalValue.h"
@ -123,7 +123,7 @@ static const char *getIntrinsicName(unsigned opcode) {
// PIC16TargetLowering Constructor.
PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
: TargetLowering(TM), TmpSize(0) {
: TargetLowering(TM, new PIC16TargetObjectFile(TM)), TmpSize(0) {
Subtarget = &TM.getSubtarget<PIC16Subtarget>();

View File

@ -31,36 +31,26 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
Data16bitsDirective = " dw ";
Data32bitsDirective = " dl ";
Data64bitsDirective = NULL;
RomData8bitsDirective = " dw ";
RomData16bitsDirective = " rom_di ";
RomData32bitsDirective = " rom_dl ";
ZeroDirective = NULL;
AsciiDirective = " dt ";
AscizDirective = NULL;
BSSSection_ = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS);
ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
SectionKind::ReadOnly);
DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel);
SwitchToSectionDirective = "";
// Need because otherwise a .text symbol is emitted by DwarfWriter
// in BeginModule, and gpasm cribbs for that .text symbol.
TextSection = getOrCreateSection("", true, SectionKind::Text);
PIC16Section *ROSection = new PIC16Section(getReadOnlySection());
ROSections.push_back(ROSection);
// FIXME: I don't know what the classification of these sections really is.
ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
false,
SectionKind::Metadata));
ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
false,
SectionKind::Metadata));
RomData8bitsDirective = " dw ";
RomData16bitsDirective = " rom_di ";
RomData32bitsDirective = " rom_dl ";
// Set it to false because we weed to generate c file name and not bc file
// name.
HasSingleParameterDotFile = false;
}
const char *PIC16TargetAsmInfo::getRomDirective(unsigned Size) const {
const char *PIC16TargetAsmInfo::
getDataASDirective(unsigned Size, unsigned AS) const {
if (AS != PIC16ISD::ROM_SPACE)
return 0;
switch (Size) {
case 8: return RomData8bitsDirective;
case 16: return RomData16bitsDirective;
@ -69,369 +59,3 @@ const char *PIC16TargetAsmInfo::getRomDirective(unsigned Size) const {
}
}
const char *PIC16TargetAsmInfo::
getDataASDirective(unsigned Size, unsigned AS) const {
if (AS == PIC16ISD::ROM_SPACE)
return getRomDirective(Size);
return NULL;
}
const Section *
PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
assert(GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all BSS Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundBSS = NULL;
for (unsigned i = 0; i < BSSSections.size(); i++) {
if (DataBankSize - BSSSections[i]->Size >= ValSize) {
FoundBSS = BSSSections[i];
break;
}
}
// No BSS section spacious enough was found. Crate a new one.
if (!FoundBSS) {
std::string name = PAN::getUdataSectionName(BSSSections.size());
const Section *NewSection = getOrCreateSection(name.c_str(), false,
// FIXME.
SectionKind::Metadata);
FoundBSS = new PIC16Section(NewSection);
// Add this newly created BSS section to the list of BSSSections.
BSSSections.push_back(FoundBSS);
}
// Insert the GV into this BSS.
FoundBSS->Items.push_back(GV);
FoundBSS->Size += ValSize;
return FoundBSS->S_;
}
const Section *
PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
assert(GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert(!C->isNullValue() && "initialized globals has zero initializer");
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
"can split initialized RAM data only");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all IDATA Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundIDATA = NULL;
for (unsigned i = 0; i < IDATASections.size(); i++) {
if (DataBankSize - IDATASections[i]->Size >= ValSize) {
FoundIDATA = IDATASections[i];
break;
}
}
// No IDATA section spacious enough was found. Crate a new one.
if (!FoundIDATA) {
std::string name = PAN::getIdataSectionName(IDATASections.size());
const Section *NewSection = getOrCreateSection(name.c_str(),
false,
// FIXME.
SectionKind::Metadata);
FoundIDATA = new PIC16Section(NewSection);
// Add this newly created IDATA section to the list of IDATASections.
IDATASections.push_back(FoundIDATA);
}
// Insert the GV into this IDATA.
FoundIDATA->Items.push_back(GV);
FoundIDATA->Size += ValSize;
return FoundIDATA->S_;
}
// Get the section for an automatic variable of a function.
// For PIC16 they are globals only with mangled names.
const Section *
PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
const std::string name = PAN::getSectionNameForSym(GV->getName());
// Go through all Auto Sections and assign this variable
// to the appropriate section.
PIC16Section *FoundAutoSec = NULL;
for (unsigned i = 0; i < AutosSections.size(); i++) {
if (AutosSections[i]->S_->getName() == name) {
FoundAutoSec = AutosSections[i];
break;
}
}
// No Auto section was found. Crate a new one.
if (!FoundAutoSec) {
const Section *NewSection = getOrCreateSection(name.c_str(),
// FIXME.
false,
SectionKind::Metadata);
FoundAutoSec = new PIC16Section(NewSection);
// Add this newly created autos section to the list of AutosSections.
AutosSections.push_back(FoundAutoSec);
}
// Insert the auto into this section.
FoundAutoSec->Items.push_back(GV);
return FoundAutoSec->S_;
}
// Override default implementation to put the true globals into
// multiple data sections if required.
const Section*
PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1,
SectionKind Kind) const {
// We select the section based on the initializer here, so it really
// has to be a GlobalVariable.
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
if (!GV)
return TargetAsmInfo::SelectSectionForGlobal(GV1, Kind);
// Record External Var Decls.
if (GV->isDeclaration()) {
ExternalVarDecls->Items.push_back(GV);
return ExternalVarDecls->S_;
}
assert(GV->hasInitializer() && "A def without initializer?");
// First, if this is an automatic variable for a function, get the section
// name for it and return.
std::string name = GV->getName();
if (PAN::isLocalName(name))
return getSectionForAuto(GV);
// Record Exteranl Var Defs.
if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
ExternalVarDefs->Items.push_back(GV);
// See if this is an uninitialized global.
const Constant *C = GV->getInitializer();
if (C->isNullValue())
return getBSSSectionForGlobal(GV);
// If this is initialized data in RAM. Put it in the correct IDATA section.
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
return getIDATASectionForGlobal(GV);
// This is initialized data in rom, put it in the readonly section.
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
return getROSectionForGlobal(GV);
// Else let the default implementation take care of it.
return TargetAsmInfo::SelectSectionForGlobal(GV, Kind);
}
PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
for (unsigned i = 0; i < BSSSections.size(); i++)
delete BSSSections[i];
for (unsigned i = 0; i < IDATASections.size(); i++)
delete IDATASections[i];
for (unsigned i = 0; i < AutosSections.size(); i++)
delete AutosSections[i];
for (unsigned i = 0; i < ROSections.size(); i++)
delete ROSections[i];
delete ExternalVarDecls;
delete ExternalVarDefs;
}
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
const Section *
PIC16TargetAsmInfo::getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const {
// If GV has a sectin name or section address create that section now.
if (GV->hasSection()) {
if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
std::string SectName = GVar->getSection();
// If address for a variable is specified, get the address and create
// section.
std::string AddrStr = "Address=";
if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
std::string SectAddr = SectName.substr(AddrStr.length());
return CreateSectionForGlobal(GVar, SectAddr);
}
// Create the section specified with section attribute.
return CreateSectionForGlobal(GVar);
}
}
return 0;
}
// Create a new section for global variable. If Addr is given then create
// section at that address else create by name.
const Section *
PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalVariable *GV,
const std::string &Addr) const {
// See if this is an uninitialized global.
const Constant *C = GV->getInitializer();
if (C->isNullValue())
return CreateBSSSectionForGlobal(GV, Addr);
// If this is initialized data in RAM. Put it in the correct IDATA section.
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
return CreateIDATASectionForGlobal(GV, Addr);
// This is initialized data in rom, put it in the readonly section.
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
return CreateROSectionForGlobal(GV, Addr);
// Else let the default implementation take care of it.
return TargetAsmInfo::SectionForGlobal(GV);
}
// Create uninitialized section for a variable.
const Section *
PIC16TargetAsmInfo::CreateBSSSectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->hasInitializer() && "This global doesn't need space");
assert(GV->getInitializer()->isNullValue() &&
"Unitialized global has non-zero initializer");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundBSS = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " UDATA";
for (unsigned i = 0; i < BSSSections.size(); i++) {
if (BSSSections[i]->S_->getName() == Name) {
FoundBSS = BSSSections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewBSS = FoundBSS;
if (NewBSS == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false, SectionKind::BSS);
NewBSS = new PIC16Section(NewSection);
BSSSections.push_back(NewBSS);
}
// Insert the GV into this BSS.
NewBSS->Items.push_back(GV);
// We do not want to put any GV without explicit section into this section
// so set its size to DatabankSize.
NewBSS->Size = DataBankSize;
return NewBSS->S_;
}
// Get rom section for a variable. Currently there can be only one rom section
// unless a variable explicitly requests a section.
const Section *
PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const {
ROSections[0]->Items.push_back(GV);
return ROSections[0]->S_;
}
// Create initialized data section for a variable.
const Section *
PIC16TargetAsmInfo::CreateIDATASectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->hasInitializer() && "This global doesn't need space");
assert(!GV->getInitializer()->isNullValue() &&
"initialized global has zero initializer");
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
"can be used for initialized RAM data only");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundIDATASec = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " IDATA";
for (unsigned i = 0; i < IDATASections.size(); i++) {
if (IDATASections[i]->S_->getName() == Name) {
FoundIDATASec = IDATASections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewIDATASec = FoundIDATASec;
if (NewIDATASec == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false,
// FIXME:
SectionKind::Metadata);
NewIDATASec = new PIC16Section(NewSection);
IDATASections.push_back(NewIDATASec);
}
// Insert the GV into this IDATA Section.
NewIDATASec->Items.push_back(GV);
// We do not want to put any GV without explicit section into this section
// so set its size to DatabankSize.
NewIDATASec->Size = DataBankSize;
return NewIDATASec->S_;
}
// Create a section in rom for a variable.
const Section *
PIC16TargetAsmInfo::CreateROSectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
"can be used for ROM data only");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundROSec = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " ROMDATA";
for (unsigned i = 1; i < ROSections.size(); i++) {
if (ROSections[i]->S_->getName() == Name) {
FoundROSec = ROSections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewRomSec = FoundROSec;
if (NewRomSec == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false,
SectionKind::ReadOnly);
NewRomSec = new PIC16Section(NewSection);
ROSections.push_back(NewRomSec);
}
// Insert the GV into this ROM Section.
NewRomSec->Items.push_back(GV);
return NewRomSec->S_;
}

View File

@ -14,91 +14,22 @@
#ifndef PIC16TARGETASMINFO_H
#define PIC16TARGETASMINFO_H
#include "PIC16.h"
#include "llvm/Target/TargetAsmInfo.h"
#include <vector>
#include "llvm/Module.h"
namespace llvm {
enum { DataBankSize = 80 };
// Forward declaration.
class PIC16TargetMachine;
class GlobalVariable;
/// PIC16 Splits the global data into mulitple udata and idata sections.
/// Each udata and idata section needs to contain a list of globals that
/// they contain, in order to avoid scanning over all the global values
/// again and printing only those that match the current section.
/// Keeping values inside the sections make printing a section much easier.
struct PIC16Section {
const Section *S_; // Connection to actual Section.
unsigned Size; // Total size of the objects contained.
bool SectionPrinted;
std::vector<const GlobalVariable*> Items;
PIC16Section(const Section *s) {
S_ = s;
Size = 0;
SectionPrinted = false;
}
bool isPrinted() const { return SectionPrinted; }
void setPrintedStatus(bool status) { SectionPrinted = status; }
};
struct PIC16TargetAsmInfo : public TargetAsmInfo {
std::string getSectionNameForSym(const std::string &Sym) const;
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
mutable std::vector<PIC16Section *> BSSSections;
mutable std::vector<PIC16Section *> IDATASections;
mutable std::vector<PIC16Section *> AutosSections;
mutable std::vector<PIC16Section *> ROSections;
mutable PIC16Section *ExternalVarDecls;
mutable PIC16Section *ExternalVarDefs;
virtual ~PIC16TargetAsmInfo();
private:
class PIC16TargetAsmInfo : public TargetAsmInfo {
const char *RomData8bitsDirective;
const char *RomData16bitsDirective;
const char *RomData32bitsDirective;
const char *getRomDirective(unsigned size) const;
public:
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
virtual const char *getDataASDirective(unsigned size, unsigned AS) const;
const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
const Section *getSectionForAuto(const GlobalVariable *GV) const;
const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
const Section *getROSectionForGlobal(const GlobalVariable *GV) const;
const Section *CreateROSectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const;
const Section *CreateSectionForGlobal(const GlobalVariable *GV,
const std::string &Addr = "") const;
public:
void SetSectionForGVs(Module &M);
const std::vector<PIC16Section*> &getBSSSections() const {
return BSSSections;
}
const std::vector<PIC16Section*> &getIDATASections() const {
return IDATASections;
}
const std::vector<PIC16Section*> &getAutosSections() const {
return AutosSections;
}
const std::vector<PIC16Section*> &getROSections() const {
return ROSections;
}
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
virtual const Section *
getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const;
};
} // namespace llvm

View File

@ -0,0 +1,401 @@
//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PIC16TargetObjectFile.h"
#include "PIC16ISelLowering.h"
#include "PIC16TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
using namespace llvm;
PIC16TargetObjectFile::PIC16TargetObjectFile(const PIC16TargetMachine &tm)
: TM (tm) {
BSSSection_ = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS);
ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
SectionKind::ReadOnly);
DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel);
// Need because otherwise a .text symbol is emitted by DwarfWriter
// in BeginModule, and gpasm cribbs for that .text symbol.
TextSection = getOrCreateSection("", true, SectionKind::Text);
PIC16Section *ROSection = new PIC16Section(ReadOnlySection);
ROSections.push_back(ROSection);
// FIXME: I don't know what the classification of these sections really is.
ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
false,
SectionKind::Metadata));
ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
false,
SectionKind::Metadata));
}
const Section *
PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const {
assert(GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all BSS Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundBSS = NULL;
for (unsigned i = 0; i < BSSSections.size(); i++) {
if (DataBankSize - BSSSections[i]->Size >= ValSize) {
FoundBSS = BSSSections[i];
break;
}
}
// No BSS section spacious enough was found. Crate a new one.
if (!FoundBSS) {
std::string name = PAN::getUdataSectionName(BSSSections.size());
const Section *NewSection = getOrCreateSection(name.c_str(), false,
// FIXME.
SectionKind::Metadata);
FoundBSS = new PIC16Section(NewSection);
// Add this newly created BSS section to the list of BSSSections.
BSSSections.push_back(FoundBSS);
}
// Insert the GV into this BSS.
FoundBSS->Items.push_back(GV);
FoundBSS->Size += ValSize;
return FoundBSS->S_;
}
const Section *
PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{
assert(GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert(!C->isNullValue() && "initialized globals has zero initializer");
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
"can split initialized RAM data only");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all IDATA Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundIDATA = NULL;
for (unsigned i = 0; i < IDATASections.size(); i++) {
if (DataBankSize - IDATASections[i]->Size >= ValSize) {
FoundIDATA = IDATASections[i];
break;
}
}
// No IDATA section spacious enough was found. Crate a new one.
if (!FoundIDATA) {
std::string name = PAN::getIdataSectionName(IDATASections.size());
const Section *NewSection = getOrCreateSection(name.c_str(),
false,
// FIXME.
SectionKind::Metadata);
FoundIDATA = new PIC16Section(NewSection);
// Add this newly created IDATA section to the list of IDATASections.
IDATASections.push_back(FoundIDATA);
}
// Insert the GV into this IDATA.
FoundIDATA->Items.push_back(GV);
FoundIDATA->Size += ValSize;
return FoundIDATA->S_;
}
// Get the section for an automatic variable of a function.
// For PIC16 they are globals only with mangled names.
const Section *
PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
const std::string name = PAN::getSectionNameForSym(GV->getName());
// Go through all Auto Sections and assign this variable
// to the appropriate section.
PIC16Section *FoundAutoSec = NULL;
for (unsigned i = 0; i < AutosSections.size(); i++) {
if (AutosSections[i]->S_->getName() == name) {
FoundAutoSec = AutosSections[i];
break;
}
}
// No Auto section was found. Crate a new one.
if (!FoundAutoSec) {
const Section *NewSection = getOrCreateSection(name.c_str(),
// FIXME.
false,
SectionKind::Metadata);
FoundAutoSec = new PIC16Section(NewSection);
// Add this newly created autos section to the list of AutosSections.
AutosSections.push_back(FoundAutoSec);
}
// Insert the auto into this section.
FoundAutoSec->Items.push_back(GV);
return FoundAutoSec->S_;
}
// Override default implementation to put the true globals into
// multiple data sections if required.
const Section*
PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
SectionKind Kind,
const TargetMachine &TM) const {
// We select the section based on the initializer here, so it really
// has to be a GlobalVariable.
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
if (!GV)
return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, TM);
// Record External Var Decls.
if (GV->isDeclaration()) {
ExternalVarDecls->Items.push_back(GV);
return ExternalVarDecls->S_;
}
assert(GV->hasInitializer() && "A def without initializer?");
// First, if this is an automatic variable for a function, get the section
// name for it and return.
std::string name = GV->getName();
if (PAN::isLocalName(name))
return getSectionForAuto(GV);
// Record Exteranl Var Defs.
if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
ExternalVarDefs->Items.push_back(GV);
// See if this is an uninitialized global.
const Constant *C = GV->getInitializer();
if (C->isNullValue())
return getBSSSectionForGlobal(GV);
// If this is initialized data in RAM. Put it in the correct IDATA section.
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
return getIDATASectionForGlobal(GV);
// This is initialized data in rom, put it in the readonly section.
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
return getROSectionForGlobal(GV);
// Else let the default implementation take care of it.
return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, TM);
}
PIC16TargetObjectFile::~PIC16TargetObjectFile() {
for (unsigned i = 0; i < BSSSections.size(); i++)
delete BSSSections[i];
for (unsigned i = 0; i < IDATASections.size(); i++)
delete IDATASections[i];
for (unsigned i = 0; i < AutosSections.size(); i++)
delete AutosSections[i];
for (unsigned i = 0; i < ROSections.size(); i++)
delete ROSections[i];
delete ExternalVarDecls;
delete ExternalVarDefs;
}
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
const Section *
PIC16TargetObjectFile::getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const {
// If GV has a sectin name or section address create that section now.
if (GV->hasSection()) {
if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
std::string SectName = GVar->getSection();
// If address for a variable is specified, get the address and create
// section.
std::string AddrStr = "Address=";
if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
std::string SectAddr = SectName.substr(AddrStr.length());
return CreateSectionForGlobal(GVar, SectAddr);
}
// Create the section specified with section attribute.
return CreateSectionForGlobal(GVar);
}
}
return 0;
}
// Create a new section for global variable. If Addr is given then create
// section at that address else create by name.
const Section *
PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV,
const std::string &Addr) const {
// See if this is an uninitialized global.
const Constant *C = GV->getInitializer();
if (C->isNullValue())
return CreateBSSSectionForGlobal(GV, Addr);
// If this is initialized data in RAM. Put it in the correct IDATA section.
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
return CreateIDATASectionForGlobal(GV, Addr);
// This is initialized data in rom, put it in the readonly section.
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
return CreateROSectionForGlobal(GV, Addr);
// Else let the default implementation take care of it.
return TargetLoweringObjectFile::SectionForGlobal(GV, TM);
}
// Create uninitialized section for a variable.
const Section *
PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->hasInitializer() && "This global doesn't need space");
assert(GV->getInitializer()->isNullValue() &&
"Unitialized global has non-zero initializer");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundBSS = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " UDATA";
for (unsigned i = 0; i < BSSSections.size(); i++) {
if (BSSSections[i]->S_->getName() == Name) {
FoundBSS = BSSSections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewBSS = FoundBSS;
if (NewBSS == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false, SectionKind::BSS);
NewBSS = new PIC16Section(NewSection);
BSSSections.push_back(NewBSS);
}
// Insert the GV into this BSS.
NewBSS->Items.push_back(GV);
// We do not want to put any GV without explicit section into this section
// so set its size to DatabankSize.
NewBSS->Size = DataBankSize;
return NewBSS->S_;
}
// Get rom section for a variable. Currently there can be only one rom section
// unless a variable explicitly requests a section.
const Section *
PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const {
ROSections[0]->Items.push_back(GV);
return ROSections[0]->S_;
}
// Create initialized data section for a variable.
const Section *
PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->hasInitializer() && "This global doesn't need space");
assert(!GV->getInitializer()->isNullValue() &&
"initialized global has zero initializer");
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
"can be used for initialized RAM data only");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundIDATASec = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " IDATA";
for (unsigned i = 0; i < IDATASections.size(); i++) {
if (IDATASections[i]->S_->getName() == Name) {
FoundIDATASec = IDATASections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewIDATASec = FoundIDATASec;
if (NewIDATASec == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false,
// FIXME:
SectionKind::Metadata);
NewIDATASec = new PIC16Section(NewSection);
IDATASections.push_back(NewIDATASec);
}
// Insert the GV into this IDATA Section.
NewIDATASec->Items.push_back(GV);
// We do not want to put any GV without explicit section into this section
// so set its size to DatabankSize.
NewIDATASec->Size = DataBankSize;
return NewIDATASec->S_;
}
// Create a section in rom for a variable.
const Section *
PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV,
std::string Addr) const {
assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
"can be used for ROM data only");
std::string Name;
// If address is given then create a section at that address else create a
// section by section name specified in GV.
PIC16Section *FoundROSec = NULL;
if (Addr.empty()) {
Name = GV->getSection() + " ROMDATA";
for (unsigned i = 1; i < ROSections.size(); i++) {
if (ROSections[i]->S_->getName() == Name) {
FoundROSec = ROSections[i];
break;
}
}
} else {
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
}
PIC16Section *NewRomSec = FoundROSec;
if (NewRomSec == NULL) {
const Section *NewSection = getOrCreateSection(Name.c_str(),
false,
SectionKind::ReadOnly);
NewRomSec = new PIC16Section(NewSection);
ROSections.push_back(NewRomSec);
}
// Insert the GV into this ROM Section.
NewRomSec->Items.push_back(GV);
return NewRomSec->S_;
}

View File

@ -0,0 +1,100 @@
//===-- PIC16TargetObjectFile.h - PIC16 Object Info -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
#define LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
#include "llvm/Target/TargetLoweringObjectFile.h"
#include <vector>
namespace llvm {
class GlobalVariable;
class Module;
class PIC16TargetMachine;
enum { DataBankSize = 80 };
/// PIC16 Splits the global data into mulitple udata and idata sections.
/// Each udata and idata section needs to contain a list of globals that
/// they contain, in order to avoid scanning over all the global values
/// again and printing only those that match the current section.
/// Keeping values inside the sections make printing a section much easier.
///
/// FIXME: Reimplement by inheriting from MCSection.
///
struct PIC16Section {
const Section *S_; // Connection to actual Section.
unsigned Size; // Total size of the objects contained.
bool SectionPrinted;
std::vector<const GlobalVariable*> Items;
PIC16Section(const Section *s) {
S_ = s;
Size = 0;
SectionPrinted = false;
}
bool isPrinted() const { return SectionPrinted; }
void setPrintedStatus(bool status) { SectionPrinted = status; }
};
class PIC16TargetObjectFile : public TargetLoweringObjectFile {
const PIC16TargetMachine &TM;
public:
mutable std::vector<PIC16Section*> BSSSections;
mutable std::vector<PIC16Section*> IDATASections;
mutable std::vector<PIC16Section*> AutosSections;
mutable std::vector<PIC16Section*> ROSections;
mutable PIC16Section *ExternalVarDecls;
mutable PIC16Section *ExternalVarDefs;
PIC16TargetObjectFile(const PIC16TargetMachine &TM);
~PIC16TargetObjectFile();
/// getSpecialCasedSectionGlobals - Allow the target to completely override
/// section assignment of a global.
virtual const Section *
getSpecialCasedSectionGlobals(const GlobalValue *GV,
SectionKind Kind) const;
virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
const TargetMachine&) const;
private:
std::string getSectionNameForSym(const std::string &Sym) const;
const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
const Section *getSectionForAuto(const GlobalVariable *GV) const;
const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
const Section *getROSectionForGlobal(const GlobalVariable *GV) const;
const Section *CreateROSectionForGlobal(const GlobalVariable *GV,
std::string Addr = "") const;
const Section *CreateSectionForGlobal(const GlobalVariable *GV,
const std::string &Addr = "") const;
public:
void SetSectionForGVs(Module &M);
const std::vector<PIC16Section*> &getBSSSections() const {
return BSSSections;
}
const std::vector<PIC16Section*> &getIDATASections() const {
return IDATASections;
}
const std::vector<PIC16Section*> &getAutosSections() const {
return AutosSections;
}
const std::vector<PIC16Section*> &getROSections() const {
return ROSections;
}
};
} // end namespace llvm
#endif

View File

@ -40,6 +40,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
@ -590,7 +591,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Print out labels for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
@ -639,7 +640,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
// Emit post-function debug information.
DW->EndFunction(&MF);
@ -681,7 +682,7 @@ void PPCLinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
if (C->isNullValue() && /* FIXME: Verify correct */
!GVar->hasSection() &&
@ -762,7 +763,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Print out labels for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
@ -861,7 +862,7 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) {
SwitchToTextSection("\t.section __TEXT,__symbol_stub1,symbol_stubs,"
"pure_instructions,16");
}
SwitchToSection(TAI->getTextSection());
SwitchToSection(getObjFileLowering().getTextSection());
return Result;
}
@ -891,7 +892,7 @@ void PPCDarwinAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
const Section *TheSection = TAI->SectionForGlobal(GVar);
const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM);
SwitchToSection(TheSection);
if (C->isNullValue() && /* FIXME: Verify correct */
@ -1051,7 +1052,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
}
if (!HiddenGVStubs.empty()) {
SwitchToSection(TAI->getDataSection());
SwitchToSection(getObjFileLowering().getDataSection());
EmitAlignment(isPPC64 ? 3 : 2);
for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(),
E = HiddenGVStubs.end(); I != E; ++I) {

View File

@ -31,6 +31,7 @@
#include "llvm/Intrinsics.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@ -56,8 +57,15 @@ static cl::opt<bool> EnablePPCPreinc("enable-ppc-preinc",
cl::desc("enable preincrement load/store generation on PPC (experimental)"),
cl::Hidden);
static TargetLoweringObjectFile *CreateTLOF(const PPCTargetMachine &TM) {
if (TM.getSubtargetImpl()->isDarwin())
return new TargetLoweringObjectFileMachO();
return new TargetLoweringObjectFileELF(false, true);
}
PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
: TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) {
: TargetLowering(TM, CreateTLOF(TM)), PPCSubTarget(*TM.getSubtargetImpl()) {
setPow2DivIsCheap();

View File

@ -70,9 +70,6 @@ PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
WeakRefDirective = "\t.weak\t";
BSSSection = "\t.section\t\".sbss\",\"aw\",@nobits";
// PPC/Linux normally uses named section for BSS.
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
// Debug Information
AbsoluteDebugSectionOffsets = true;
SupportsDebugInformation = true;

View File

@ -26,6 +26,7 @@
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@ -95,7 +96,7 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Print out the label for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
EmitAlignment(MF.getAlignment(), F);
O << "\t.globl\t" << CurrentFnName << '\n';
@ -229,7 +230,7 @@ void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
printVisibility(name, GVar->getVisibility());
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
if (C->isNullValue() && !GVar->hasSection()) {
if (!GVar->isThreadLocal() &&

View File

@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@ -548,9 +549,31 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
}
}
class TargetLoweringObjectFileSparc : public TargetLoweringObjectFileELF {
public:
void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
if (Kind.isMergeableConst() || Kind.isMergeableCString())
return TargetLoweringObjectFileELF::getSectionFlagsAsString(Kind, Str);
// FIXME: Inefficient.
std::string Res;
if (!Kind.isMetadata())
Res += ",#alloc";
if (Kind.isText())
Res += ",#execinstr";
if (Kind.isWriteable())
Res += ",#write";
if (Kind.isThreadLocal())
Res += ",#tls";
Str.append(Res.begin(), Res.end());
}
};
SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
: TargetLowering(TM) {
: TargetLowering(TM, new TargetLoweringObjectFileSparc()) {
// Set up the register classes.
addRegisterClass(MVT::i32, SP::IntRegsRegisterClass);

View File

@ -25,27 +25,6 @@ SparcELFTargetAsmInfo::SparcELFTargetAsmInfo(const TargetMachine &TM)
ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
COMMDirectiveTakesAlignment = true;
CStringSection=".rodata.str";
// Sparc normally uses named section for BSS.
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
}
void SparcELFTargetAsmInfo::getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const {
if (Kind.isMergeableConst() || Kind.isMergeableCString())
return ELFTargetAsmInfo::getSectionFlagsAsString(Kind, Str);
// FIXME: Inefficient.
std::string Res;
if (!Kind.isMetadata())
Res += ",#alloc";
if (Kind.isText())
Res += ",#execinstr";
if (Kind.isWriteable())
Res += ",#write";
if (Kind.isThreadLocal())
Res += ",#tls";
Str.append(Res.begin(), Res.end());
}

View File

@ -23,10 +23,6 @@ namespace llvm {
struct SparcELFTargetAsmInfo : public ELFTargetAsmInfo {
explicit SparcELFTargetAsmInfo(const TargetMachine &TM);
virtual void getSectionFlagsAsString(SectionKind Kind,
SmallVectorImpl<char> &Str) const;
};
} // namespace llvm

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
@ -82,7 +83,7 @@ void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
unsigned FnAlign = MF.getAlignment();
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
EmitAlignment(FnAlign, F);
@ -330,7 +331,7 @@ void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
O << "\t.type\t" << name << ",@object\n";
SwitchToSection(TAI->SectionForGlobal(GVar));
SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, TM));
if (C->isNullValue() && !GVar->hasSection() &&
!GVar->isThreadLocal() &&

View File

@ -31,13 +31,15 @@
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/VectorExtras.h"
using namespace llvm;
SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
TargetLowering(tm), Subtarget(*tm.getSubtargetImpl()), TM(tm) {
TargetLowering(tm, new TargetLoweringObjectFileELF()),
Subtarget(*tm.getSubtargetImpl()), TM(tm) {
RegInfo = TM.getRegisterInfo();

View File

@ -27,6 +27,4 @@ SystemZTargetAsmInfo::SystemZTargetAsmInfo(const SystemZTargetMachine &TM)
PCSymbol = ".";
NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
}

View File

@ -30,10 +30,6 @@ using namespace llvm;
TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) : TM(tm) {
BSSSection = "\t.bss";
BSSSection_ = 0;
ReadOnlySection = 0;
TLSDataSection = 0;
TLSBSSSection = 0;
ZeroFillDirective = 0;
NonexecutableStackDirective = 0;
NeedsSet = false;
@ -78,7 +74,6 @@ TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) : TM(tm) {
JumpTableDataSection = "\t.section .rodata";
JumpTableDirective = 0;
CStringSection = 0;
CStringSection_ = 0;
// FIXME: Flags are ELFish - replace with normal section stuff.
StaticCtorsSection = "\t.section .ctors,\"aw\",@progbits";
StaticDtorsSection = "\t.section .dtors,\"aw\",@progbits";
@ -158,219 +153,6 @@ unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
return dwarf::DW_EH_PE_absptr;
}
static bool isSuitableForBSS(const GlobalVariable *GV) {
Constant *C = GV->getInitializer();
// Must have zero initializer.
if (!C->isNullValue())
return false;
// Leave constant zeros in readonly constant sections, so they can be shared.
if (GV->isConstant())
return false;
// If the global has an explicit section specified, don't put it in BSS.
if (!GV->getSection().empty())
return false;
// If -nozero-initialized-in-bss is specified, don't ever use BSS.
if (NoZerosInBSS)
return false;
// Otherwise, put it in BSS!
return true;
}
static bool isConstantString(const Constant *C) {
// First check: is we have constant array of i8 terminated with zero
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
// Check, if initializer is a null-terminated string
if (CVA && CVA->isCString())
return true;
// Another possibility: [1 x i8] zeroinitializer
if (isa<ConstantAggregateZero>(C))
if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType()))
return (Ty->getElementType() == Type::Int8Ty &&
Ty->getNumElements() == 1);
return false;
}
static SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV,
const TargetMachine &TM) {
Reloc::Model ReloModel = TM.getRelocationModel();
// Early exit - functions should be always in text sections.
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
if (GVar == 0)
return SectionKind::Text;
// Handle thread-local data first.
if (GVar->isThreadLocal()) {
if (isSuitableForBSS(GVar))
return SectionKind::ThreadBSS;
return SectionKind::ThreadData;
}
// Variable can be easily put to BSS section.
if (isSuitableForBSS(GVar))
return SectionKind::BSS;
Constant *C = GVar->getInitializer();
// If the global is marked constant, we can put it into a mergable section,
// a mergable string section, or general .data if it contains relocations.
if (GVar->isConstant()) {
// If the initializer for the global contains something that requires a
// relocation, then we may have to drop this into a wriable data section
// even though it is marked const.
switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation:
// If initializer is a null-terminated string, put it in a "cstring"
// section if the target has it.
if (isConstantString(C))
return SectionKind::MergeableCString;
// Otherwise, just drop it into a mergable constant section. If we have
// a section for this size, use it, otherwise use the arbitrary sized
// mergable section.
switch (TM.getTargetData()->getTypeAllocSize(C->getType())) {
case 4: return SectionKind::MergeableConst4;
case 8: return SectionKind::MergeableConst8;
case 16: return SectionKind::MergeableConst16;
default: return SectionKind::MergeableConst;
}
case Constant::LocalRelocation:
// In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app
// starts up. However, we can't put this into a mergable section, because
// the linker doesn't take relocations into consideration when it tries to
// merge entries in the section.
if (ReloModel == Reloc::Static)
return SectionKind::ReadOnly;
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel.local section.
return SectionKind::ReadOnlyWithRelLocal;
case Constant::GlobalRelocations:
// In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app
// starts up. However, we can't put this into a mergable section, because
// the linker doesn't take relocations into consideration when it tries to
// merge entries in the section.
if (ReloModel == Reloc::Static)
return SectionKind::ReadOnly;
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel section.
return SectionKind::ReadOnlyWithRel;
}
}
// Okay, this isn't a constant. If the initializer for the global is going
// to require a runtime relocation by the dynamic linker, put it into a more
// specific section to improve startup time of the app. This coalesces these
// globals together onto fewer pages, improving the locality of the dynamic
// linker.
if (ReloModel == Reloc::Static)
return SectionKind::DataNoRel;
switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation:
return SectionKind::DataNoRel;
case Constant::LocalRelocation:
return SectionKind::DataRelLocal;
case Constant::GlobalRelocations:
return SectionKind::DataRel;
}
}
/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition. This should not
/// be passed external (or available externally) globals.
const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
"Can only be used for global definitions");
SectionKind::Kind GVKind = SectionKindForGlobal(GV, TM);
SectionKind Kind = SectionKind::get(GVKind, GV->isWeakForLinker(),
GV->hasSection());
// Select section name.
if (GV->hasSection()) {
// If the target has special section hacks for specifically named globals,
// return them now.
if (const Section *TS = getSpecialCasedSectionGlobals(GV, Kind))
return TS;
// If the target has magic semantics for certain section names, make sure to
// pick up the flags. This allows the user to write things with attribute
// section and still get the appropriate section flags printed.
GVKind = getKindForNamedSection(GV->getSection().c_str(), GVKind);
return getOrCreateSection(GV->getSection().c_str(), false, GVKind);
}
// Use default section depending on the 'type' of global
return SelectSectionForGlobal(GV, Kind);
}
// Lame default implementation. Calculate the section name for global.
const Section*
TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const {
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
if (Kind.isText())
return getTextSection();
if (Kind.isBSS())
if (const Section *S = getBSSSection_())
return S;
if (Kind.isReadOnly())
if (const Section *S = getReadOnlySection())
return S;
return getDataSection();
}
/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
TargetAsmInfo::getSectionForMergeableConstant(SectionKind Kind) const {
if (Kind.isReadOnly())
if (const Section *S = getReadOnlySection())
return S;
return getDataSection();
}
const Section *TargetAsmInfo::getOrCreateSection(const char *Name,
bool isDirective,
SectionKind::Kind Kind) const {
Section &S = Sections[Name];
// This is newly-created section, set it up properly.
if (S.Name.empty()) {
S.Kind = SectionKind::get(Kind, false /*weak*/, !isDirective);
S.Name = Name;
}
return &S;
}
unsigned TargetAsmInfo::getULEB128Size(unsigned Value) {
unsigned Size = 0;
do {

View File

@ -0,0 +1,647 @@
//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements classes used to handle lowerings specific to common
// object file formats.
//
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Generic Code
//===----------------------------------------------------------------------===//
TargetLoweringObjectFile::TargetLoweringObjectFile() {
TextSection = 0;
DataSection = 0;
BSSSection_ = 0;
ReadOnlySection = 0;
TLSDataSection = 0;
TLSBSSSection = 0;
CStringSection_ = 0;
}
TargetLoweringObjectFile::~TargetLoweringObjectFile() {
}
static bool isSuitableForBSS(const GlobalVariable *GV) {
Constant *C = GV->getInitializer();
// Must have zero initializer.
if (!C->isNullValue())
return false;
// Leave constant zeros in readonly constant sections, so they can be shared.
if (GV->isConstant())
return false;
// If the global has an explicit section specified, don't put it in BSS.
if (!GV->getSection().empty())
return false;
// If -nozero-initialized-in-bss is specified, don't ever use BSS.
if (NoZerosInBSS)
return false;
// Otherwise, put it in BSS!
return true;
}
static bool isConstantString(const Constant *C) {
// First check: is we have constant array of i8 terminated with zero
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
// Check, if initializer is a null-terminated string
if (CVA && CVA->isCString())
return true;
// Another possibility: [1 x i8] zeroinitializer
if (isa<ConstantAggregateZero>(C))
if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType()))
return (Ty->getElementType() == Type::Int8Ty &&
Ty->getNumElements() == 1);
return false;
}
static SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV,
const TargetMachine &TM) {
Reloc::Model ReloModel = TM.getRelocationModel();
// Early exit - functions should be always in text sections.
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
if (GVar == 0)
return SectionKind::Text;
// Handle thread-local data first.
if (GVar->isThreadLocal()) {
if (isSuitableForBSS(GVar))
return SectionKind::ThreadBSS;
return SectionKind::ThreadData;
}
// Variable can be easily put to BSS section.
if (isSuitableForBSS(GVar))
return SectionKind::BSS;
Constant *C = GVar->getInitializer();
// If the global is marked constant, we can put it into a mergable section,
// a mergable string section, or general .data if it contains relocations.
if (GVar->isConstant()) {
// If the initializer for the global contains something that requires a
// relocation, then we may have to drop this into a wriable data section
// even though it is marked const.
switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation:
// If initializer is a null-terminated string, put it in a "cstring"
// section if the target has it.
if (isConstantString(C))
return SectionKind::MergeableCString;
// Otherwise, just drop it into a mergable constant section. If we have
// a section for this size, use it, otherwise use the arbitrary sized
// mergable section.
switch (TM.getTargetData()->getTypeAllocSize(C->getType())) {
case 4: return SectionKind::MergeableConst4;
case 8: return SectionKind::MergeableConst8;
case 16: return SectionKind::MergeableConst16;
default: return SectionKind::MergeableConst;
}
case Constant::LocalRelocation:
// In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app
// starts up. However, we can't put this into a mergable section, because
// the linker doesn't take relocations into consideration when it tries to
// merge entries in the section.
if (ReloModel == Reloc::Static)
return SectionKind::ReadOnly;
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel.local section.
return SectionKind::ReadOnlyWithRelLocal;
case Constant::GlobalRelocations:
// In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app
// starts up. However, we can't put this into a mergable section, because
// the linker doesn't take relocations into consideration when it tries to
// merge entries in the section.
if (ReloModel == Reloc::Static)
return SectionKind::ReadOnly;
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel section.
return SectionKind::ReadOnlyWithRel;
}
}
// Okay, this isn't a constant. If the initializer for the global is going
// to require a runtime relocation by the dynamic linker, put it into a more
// specific section to improve startup time of the app. This coalesces these
// globals together onto fewer pages, improving the locality of the dynamic
// linker.
if (ReloModel == Reloc::Static)
return SectionKind::DataNoRel;
switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation:
return SectionKind::DataNoRel;
case Constant::LocalRelocation:
return SectionKind::DataRelLocal;
case Constant::GlobalRelocations:
return SectionKind::DataRel;
}
}
/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition. This should not
/// be passed external (or available externally) globals.
const Section *TargetLoweringObjectFile::
SectionForGlobal(const GlobalValue *GV, const TargetMachine &TM) const {
assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
"Can only be used for global definitions");
SectionKind::Kind GVKind = SectionKindForGlobal(GV, TM);
SectionKind Kind = SectionKind::get(GVKind, GV->isWeakForLinker(),
GV->hasSection());
// Select section name.
if (GV->hasSection()) {
// If the target has special section hacks for specifically named globals,
// return them now.
if (const Section *TS = getSpecialCasedSectionGlobals(GV, Kind))
return TS;
// If the target has magic semantics for certain section names, make sure to
// pick up the flags. This allows the user to write things with attribute
// section and still get the appropriate section flags printed.
GVKind = getKindForNamedSection(GV->getSection().c_str(), GVKind);
return getOrCreateSection(GV->getSection().c_str(), false, GVKind);
}
// Use default section depending on the 'type' of global
return SelectSectionForGlobal(GV, Kind, TM);
}
// Lame default implementation. Calculate the section name for global.
const Section*
TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
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();
}
/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
TargetLoweringObjectFile::
getSectionForMergeableConstant(SectionKind Kind) const {
if (Kind.isReadOnly() && ReadOnlySection != 0)
return ReadOnlySection;
return DataSection;
}
const Section *TargetLoweringObjectFile::
getOrCreateSection(const char *Name, bool isDirective,
SectionKind::Kind Kind) const {
Section &S = Sections[Name];
// This is newly-created section, set it up properly.
if (S.Name.empty()) {
S.Kind = SectionKind::get(Kind, false /*weak*/, !isDirective);
S.Name = Name;
}
return &S;
}
//===----------------------------------------------------------------------===//
// ELF
//===----------------------------------------------------------------------===//
TargetLoweringObjectFileELF::TargetLoweringObjectFileELF(bool atIsCommentChar,
bool HasCrazyBSS)
: AtIsCommentChar(atIsCommentChar) {
if (!HasCrazyBSS)
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
else
// PPC/Linux doesn't support the .bss directive, it needs .section .bss.
// FIXME: Does .section .bss work everywhere??
BSSSection_ = getOrCreateSection("\t.bss", false, SectionKind::BSS);
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel);
ReadOnlySection =
getOrCreateSection("\t.rodata", false, SectionKind::ReadOnly);
TLSDataSection =
getOrCreateSection("\t.tdata", false, SectionKind::ThreadData);
CStringSection_ = getOrCreateSection("\t.rodata.str", true,
SectionKind::MergeableCString);
TLSBSSSection = getOrCreateSection("\t.tbss", false, SectionKind::ThreadBSS);
DataRelSection = getOrCreateSection("\t.data.rel", false,
SectionKind::DataRel);
DataRelLocalSection = getOrCreateSection("\t.data.rel.local", false,
SectionKind::DataRelLocal);
DataRelROSection = getOrCreateSection("\t.data.rel.ro", false,
SectionKind::ReadOnlyWithRel);
DataRelROLocalSection =
getOrCreateSection("\t.data.rel.ro.local", false,
SectionKind::ReadOnlyWithRelLocal);
MergeableConst4Section = getOrCreateSection(".rodata.cst4", false,
SectionKind::MergeableConst4);
MergeableConst8Section = getOrCreateSection(".rodata.cst8", false,
SectionKind::MergeableConst8);
MergeableConst16Section = getOrCreateSection(".rodata.cst16", false,
SectionKind::MergeableConst16);
}
SectionKind::Kind TargetLoweringObjectFileELF::
getKindForNamedSection(const char *Name, SectionKind::Kind K) const {
if (Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
return SectionKind::BSS;
if (strcmp(Name, ".tdata") == 0 ||
strncmp(Name, ".tdata.", 7) == 0 ||
strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
return SectionKind::ThreadData;
if (strcmp(Name, ".tbss") == 0 ||
strncmp(Name, ".tbss.", 6) == 0 ||
strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
return SectionKind::ThreadBSS;
return K;
}
void TargetLoweringObjectFileELF::
getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl<char> &Str) const {
Str.push_back(',');
Str.push_back('"');
if (!Kind.isMetadata())
Str.push_back('a');
if (Kind.isText())
Str.push_back('x');
if (Kind.isWriteable())
Str.push_back('w');
if (Kind.isMergeableConst() || Kind.isMergeableCString())
Str.push_back('M');
if (Kind.isMergeableCString())
Str.push_back('S');
if (Kind.isThreadLocal())
Str.push_back('T');
Str.push_back('"');
Str.push_back(',');
// If comment string is '@', e.g. as on ARM - use '%' instead
if (AtIsCommentChar)
Str.push_back('%');
else
Str.push_back('@');
const char *KindStr;
if (Kind.isBSS())
KindStr = "nobits";
else
KindStr = "progbits";
Str.append(KindStr, KindStr+strlen(KindStr));
if (Kind.isMergeableCString()) {
// TODO: Eventually handle multiple byte character strings. For now, all
// mergable C strings are single byte.
Str.push_back(',');
Str.push_back('1');
} else if (Kind.isMergeableConst4()) {
Str.push_back(',');
Str.push_back('4');
} else if (Kind.isMergeableConst8()) {
Str.push_back(',');
Str.push_back('8');
} else if (Kind.isMergeableConst16()) {
Str.push_back(',');
Str.push_back('1');
Str.push_back('6');
}
}
static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText()) return ".gnu.linkonce.t.";
if (Kind.isReadOnly()) return ".gnu.linkonce.r.";
if (Kind.isThreadData()) return ".gnu.linkonce.td.";
if (Kind.isThreadBSS()) return ".gnu.linkonce.tb.";
if (Kind.isBSS()) return ".gnu.linkonce.b.";
if (Kind.isDataNoRel()) return ".gnu.linkonce.d.";
if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local.";
if (Kind.isDataRel()) return ".gnu.linkonce.d.rel.";
if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local.";
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return ".gnu.linkonce.d.rel.ro.";
}
const Section *TargetLoweringObjectFileELF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
const TargetMachine &TM) const {
// If this global is linkonce/weak and the target handles this by emitting it
// into a 'uniqued' section name, create and return the section now.
if (Kind.isWeak()) {
const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
// FIXME: Use mangler interface (PR4584).
std::string Name = Prefix+GV->getNameStr();
return getOrCreateSection(Name.c_str(), false, Kind.getKind());
}
if (Kind.isText()) return TextSection;
if (Kind.isMergeableCString()) {
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
// FIXME: This is completely wrong. Why is it comparing the size of the
// character type to 1?
/// cast<ArrayType>(C->getType())->getNumElements();
uint64_t Size = 1;
if (Size <= 16) {
assert(CStringSection_ && "Should have string section prefix");
// We also need alignment here.
// FIXME: this is getting the alignment of the character, not the
// alignment of the global!
unsigned Align =
TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV));
std::string Name = CStringSection_->getName() + utostr(Size) + '.' +
utostr(Align);
return getOrCreateSection(Name.c_str(), false,
SectionKind::MergeableCString);
}
return ReadOnlySection;
}
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return MergeableConst4Section;
if (Kind.isMergeableConst8())
return MergeableConst8Section;
if (Kind.isMergeableConst16())
return MergeableConst16Section;
return ReadOnlySection; // .const
}
if (Kind.isReadOnly()) return ReadOnlySection;
if (Kind.isThreadData()) return TLSDataSection;
if (Kind.isThreadBSS()) return TLSBSSSection;
if (Kind.isBSS()) return BSSSection_;
if (Kind.isDataNoRel()) return DataSection;
if (Kind.isDataRelLocal()) return DataRelLocalSection;
if (Kind.isDataRel()) return DataRelSection;
if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return DataRelROSection;
}
/// getSectionForMergeableConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *TargetLoweringObjectFileELF::
getSectionForMergeableConstant(SectionKind Kind) const {
if (Kind.isMergeableConst4())
return MergeableConst4Section;
if (Kind.isMergeableConst8())
return MergeableConst8Section;
if (Kind.isMergeableConst16())
return MergeableConst16Section;
if (Kind.isReadOnly())
return ReadOnlySection;
if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return DataRelROSection;
}
//===----------------------------------------------------------------------===//
// MachO
//===----------------------------------------------------------------------===//
TargetLoweringObjectFileMachO::
TargetLoweringObjectFileMachO() {
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel);
CStringSection_ = getOrCreateSection("\t.cstring", true,
SectionKind::MergeableCString);
FourByteConstantSection = getOrCreateSection("\t.literal4\n", true,
SectionKind::MergeableConst4);
EightByteConstantSection = getOrCreateSection("\t.literal8\n", true,
SectionKind::MergeableConst8);
SixteenByteConstantSection =
getOrCreateSection("\t.literal16\n", true, SectionKind::MergeableConst16);
ReadOnlySection = getOrCreateSection("\t.const", true, SectionKind::ReadOnly);
TextCoalSection =
getOrCreateSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions",
false, SectionKind::Text);
ConstTextCoalSection = getOrCreateSection("\t__TEXT,__const_coal,coalesced",
false, SectionKind::Text);
ConstDataCoalSection = getOrCreateSection("\t__DATA,__const_coal,coalesced",
false, SectionKind::Text);
ConstDataSection = getOrCreateSection("\t.const_data", true,
SectionKind::ReadOnlyWithRel);
DataCoalSection = getOrCreateSection("\t__DATA,__datacoal_nt,coalesced",
false, SectionKind::DataRel);
}
const Section *
TargetLoweringObjectFileMachO::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind,
const TargetMachine &TM) const {
assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS");
if (Kind.isText())
return Kind.isWeak() ? TextCoalSection : TextSection;
// If this is weak/linkonce, put this in a coalescable section, either in text
// or data depending on if it is writable.
if (Kind.isWeak()) {
if (Kind.isReadOnly())
return ConstTextCoalSection;
return DataCoalSection;
}
// FIXME: Alignment check should be handled by section classifier.
if (Kind.isMergeableCString()) {
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
const TargetData &TD = *TM.getTargetData();
unsigned Size = TD.getTypeAllocSize(Ty);
if (Size) {
unsigned Align = TD.getPreferredAlignment(cast<GlobalVariable>(GV));
if (Align <= 32)
return CStringSection_;
}
return ReadOnlySection;
}
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
return SixteenByteConstantSection;
return ReadOnlySection; // .const
}
// FIXME: ROData -> const in -static mode that is relocatable but they happen
// by the static linker. Why not mergeable?
if (Kind.isReadOnly())
return ReadOnlySection;
// If this is marked const, put it into a const section. But if the dynamic
// linker needs to write to it, put it in the data segment.
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
// Otherwise, just drop the variable in the normal data section.
return DataSection;
}
const Section *
TargetLoweringObjectFileMachO::
getSectionForMergeableConstant(SectionKind Kind) const {
// If this constant requires a relocation, we have to put it in the data
// segment, not in the text segment.
if (Kind.isDataRel())
return ConstDataSection;
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
return SixteenByteConstantSection;
return ReadOnlySection; // .const
}
//===----------------------------------------------------------------------===//
// COFF
//===----------------------------------------------------------------------===//
TargetLoweringObjectFileCOFF::TargetLoweringObjectFileCOFF() {
TextSection = getOrCreateSection("_text", true, SectionKind::Text);
DataSection = getOrCreateSection("_data", true, SectionKind::DataRel);
}
void TargetLoweringObjectFileCOFF::
getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl<char> &Str) const {
// FIXME: Inefficient.
std::string Res = ",\"";
if (Kind.isText())
Res += 'x';
if (Kind.isWriteable())
Res += 'w';
Res += "\"";
Str.append(Res.begin(), Res.end());
}
static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText())
return ".text$linkonce";
if (Kind.isWriteable())
return ".data$linkonce";
return ".rdata$linkonce";
}
const Section *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
const TargetMachine &TM) const {
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
// If this global is linkonce/weak and the target handles this by emitting it
// into a 'uniqued' section name, create and return the section now.
if (Kind.isWeak()) {
const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind);
// FIXME: Use mangler interface (PR4584).
std::string Name = Prefix+GV->getNameStr();
return getOrCreateSection(Name.c_str(), false, Kind.getKind());
}
if (Kind.isText())
return getTextSection();
if (Kind.isBSS())
if (const Section *S = BSSSection_)
return S;
if (Kind.isReadOnly() && ReadOnlySection != 0)
return ReadOnlySection;
return getDataSection();
}

View File

@ -37,6 +37,7 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
@ -166,7 +167,7 @@ void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
if (Subtarget->isTargetCygMing())
DecorateCygMingName(CurrentFnName, F);
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
@ -782,7 +783,7 @@ void X86ATTAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
if (Subtarget->isTargetELF())
O << "\t.type\t" << name << ",@object\n";
const Section *TheSection = TAI->SectionForGlobal(GVar);
const Section *TheSection = getObjFileLowering().SectionForGlobal(GVar, TM);
SwitchToSection(TheSection);
if (C->isNullValue() && !GVar->hasSection() &&
@ -931,7 +932,7 @@ bool X86ATTAsmPrinter::doFinalization(Module &M) {
}
if (!HiddenGVStubs.empty()) {
SwitchToSection(TAI->getDataSection());
SwitchToSection(getObjFileLowering().getDataSection());
EmitAlignment(2);
for (StringMap<std::string>::iterator I = HiddenGVStubs.begin(),
E = HiddenGVStubs.end(); I != E; ++I)

View File

@ -29,6 +29,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
@ -513,7 +514,7 @@ void X86IntelAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
O << "\tpublic " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
SwitchToSection(TAI->getDataSection());
SwitchToSection(getObjFileLowering().getDataSection());
break;
default:
llvm_unreachable("Unknown linkage type!");

View File

@ -36,6 +36,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
@ -50,8 +51,23 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX"));
static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, MVT VT, SDValue V1,
SDValue V2);
static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) {
switch (TM.getSubtarget<X86Subtarget>().TargetType) {
default: llvm_unreachable("unknown subtarget type");
case X86Subtarget::isDarwin:
return new TargetLoweringObjectFileMachO();
case X86Subtarget::isELF:
return new TargetLoweringObjectFileELF();
case X86Subtarget::isMingw:
case X86Subtarget::isCygwin:
case X86Subtarget::isWindows:
return new TargetLoweringObjectFileCOFF();
}
}
X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
: TargetLowering(TM) {
: TargetLowering(TM, createTLOF(TM)) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
X86ScalarSSEf64 = Subtarget->hasSSE2();
X86ScalarSSEf32 = Subtarget->hasSSE1();

View File

@ -121,8 +121,6 @@ X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM) :
// Set up DWARF directives
HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
// Debug Information
AbsoluteDebugSectionOffsets = true;
SupportsDebugInformation = true;
@ -252,9 +250,6 @@ X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM):
AlignmentIsInBytes = true;
TextSection = getOrCreateSection("_text", true, SectionKind::Text);
DataSection = getOrCreateSection("_data", true, SectionKind::DataRel);
JumpTableDataSection = NULL;
SwitchToSectionDirective = "";
TextSectionStartSuffix = "\tSEGMENT PARA 'CODE'";

View File

@ -33,8 +33,6 @@ namespace llvm {
}
};
typedef X86TargetAsmInfo<TargetAsmInfo> X86GenericTargetAsmInfo;
EXTERN_TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);
struct X86DarwinTargetAsmInfo : public X86TargetAsmInfo<DarwinTargetAsmInfo> {
@ -58,7 +56,7 @@ namespace llvm {
};
struct X86WinTargetAsmInfo : public X86GenericTargetAsmInfo {
struct X86WinTargetAsmInfo : public X86TargetAsmInfo<TargetAsmInfo> {
explicit X86WinTargetAsmInfo(const X86TargetMachine &TM);
};

View File

@ -32,20 +32,18 @@ extern "C" void LLVMInitializeX86Target() {
const TargetAsmInfo *X86TargetMachine::createTargetAsmInfo() const {
if (Subtarget.isFlavorIntel())
return new X86WinTargetAsmInfo(*this);
else
switch (Subtarget.TargetType) {
case X86Subtarget::isDarwin:
return new X86DarwinTargetAsmInfo(*this);
case X86Subtarget::isELF:
return new X86ELFTargetAsmInfo(*this);
case X86Subtarget::isMingw:
case X86Subtarget::isCygwin:
return new X86COFFTargetAsmInfo(*this);
case X86Subtarget::isWindows:
return new X86WinTargetAsmInfo(*this);
default:
return new X86GenericTargetAsmInfo(*this);
}
switch (Subtarget.TargetType) {
default: llvm_unreachable("unknown subtarget type");
case X86Subtarget::isDarwin:
return new X86DarwinTargetAsmInfo(*this);
case X86Subtarget::isELF:
return new X86ELFTargetAsmInfo(*this);
case X86Subtarget::isMingw:
case X86Subtarget::isCygwin:
return new X86COFFTargetAsmInfo(*this);
case X86Subtarget::isWindows:
return new X86WinTargetAsmInfo(*this);
}
}
X86_32TargetMachine::X86_32TargetMachine(const Target &T, const Module &M,

View File

@ -20,4 +20,5 @@ add_llvm_target(XCore
XCoreSubtarget.cpp
XCoreTargetAsmInfo.cpp
XCoreTargetMachine.cpp
XCoreTargetObjectFile.cpp
)

View File

@ -28,6 +28,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
@ -133,7 +134,7 @@ void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
const TargetData *TD = TM.getTargetData();
SwitchToSection(TAI->SectionForGlobal(GV));
SwitchToSection(getObjFileLowering().SectionForGlobal(GV, TM));
std::string name = Mang->getMangledName(GV);
Constant *C = GV->getInitializer();
@ -204,7 +205,7 @@ void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) {
// Print out the label for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
SwitchToSection(getObjFileLowering().SectionForGlobal(F, TM));
// Mark the start of the function
O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";

View File

@ -16,6 +16,7 @@
#include "XCoreISelLowering.h"
#include "XCoreMachineFunctionInfo.h"
#include "XCore.h"
#include "XCoreTargetObjectFile.h"
#include "XCoreTargetMachine.h"
#include "XCoreSubtarget.h"
#include "llvm/DerivedTypes.h"
@ -55,7 +56,8 @@ getTargetNodeName(unsigned Opcode) const
}
XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
: TargetLowering(XTM),
: TargetLowering(XTM,
new XCoreTargetObjectFile(XTM.getSubtargetImpl()->isXS1A())),
TM(XTM),
Subtarget(*XTM.getSubtargetImpl()) {

View File

@ -1,4 +1,4 @@
//===-- XCoreTargetAsmInfo.cpp - XCore asm properties -----------*- C++ -*-===//
//===-- XCoreTargetAsmInfo.cpp - XCore asm properties ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -6,41 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the XCoreTargetAsmInfo properties.
// We use the small section flag for the CP relative and DP relative
// flags. If a section is small and writable then it is DP relative. If a
// section is small and not writable then it is CP relative.
//
//===----------------------------------------------------------------------===//
#include "XCoreTargetAsmInfo.h"
#include "XCoreTargetMachine.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
XCoreTargetAsmInfo::XCoreTargetAsmInfo(const XCoreTargetMachine &TM)
XCoreTargetAsmInfo::XCoreTargetAsmInfo(const TargetMachine &TM)
: ELFTargetAsmInfo(TM) {
SupportsDebugInformation = true;
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.dp.data", false, SectionKind::DataRel);
BSSSection_ = getOrCreateSection("\t.dp.bss", false, SectionKind::BSS);
// TLS globals are lowered in the backend to arrays indexed by the current
// thread id. After lowering they require no special handling by the linker
// and can be placed in the standard data / bss sections.
TLSDataSection = DataSection;
TLSBSSSection = BSSSection_;
if (TM.getSubtargetImpl()->isXS1A())
// FIXME: Why is this writable???
ReadOnlySection = getOrCreateSection("\t.dp.rodata", false,
SectionKind::DataRel);
else
ReadOnlySection = getOrCreateSection("\t.cp.rodata", false,
SectionKind::ReadOnly);
Data16bitsDirective = "\t.short\t";
Data32bitsDirective = "\t.long\t";
Data64bitsDirective = 0;

View File

@ -18,13 +18,9 @@
namespace llvm {
// Forward declarations.
class XCoreTargetMachine;
class XCoreSubtarget;
class XCoreTargetAsmInfo : public ELFTargetAsmInfo {
public:
explicit XCoreTargetAsmInfo(const XCoreTargetMachine &TM);
explicit XCoreTargetAsmInfo(const TargetMachine &TM);
};
} // namespace llvm

View File

@ -0,0 +1,32 @@
//===-- XCoreTargetObjectFile.cpp - XCore object files --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "XCoreTargetObjectFile.h"
using namespace llvm;
XCoreTargetObjectFile::XCoreTargetObjectFile(bool isXS1A) {
TextSection = getOrCreateSection("\t.text", true, SectionKind::Text);
DataSection = getOrCreateSection("\t.dp.data", false, SectionKind::DataRel);
BSSSection_ = getOrCreateSection("\t.dp.bss", false, SectionKind::BSS);
// TLS globals are lowered in the backend to arrays indexed by the current
// thread id. After lowering they require no special handling by the linker
// and can be placed in the standard data / bss sections.
TLSDataSection = DataSection;
TLSBSSSection = BSSSection_;
if (isXS1A)
// FIXME: Why is this writable ("datarel")???
ReadOnlySection = getOrCreateSection("\t.dp.rodata", false,
SectionKind::DataRel);
else
ReadOnlySection = getOrCreateSection("\t.cp.rodata", false,
SectionKind::ReadOnly);
}

View File

@ -0,0 +1,25 @@
//===-- llvm/Target/XCoreTargetObjectFile.h - XCore Object Info -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_XCORE_TARGETOBJECTFILE_H
#define LLVM_TARGET_XCORE_TARGETOBJECTFILE_H
#include "llvm/Target/TargetLoweringObjectFile.h"
namespace llvm {
class XCoreTargetObjectFile : public TargetLoweringObjectFileELF {
public:
XCoreTargetObjectFile(bool isXS1A);
// TODO: Classify globals as xcore wishes.
};
} // end namespace llvm
#endif