mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
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:
parent
7988aff079
commit
f0144127b9
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
///
|
||||
|
187
include/llvm/Target/TargetLoweringObjectFile.h
Normal file
187
include/llvm/Target/TargetLoweringObjectFile.h
Normal 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
|
@ -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 ||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -10,6 +10,7 @@ add_llvm_library(LLVMTarget
|
||||
TargetFrameInfo.cpp
|
||||
TargetInstrInfo.cpp
|
||||
TargetIntrinsicInfo.cpp
|
||||
TargetLoweringObjectFile.cpp
|
||||
TargetMachOWriterInfo.cpp
|
||||
TargetMachine.cpp
|
||||
TargetRegisterInfo.cpp
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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() &&
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -17,6 +17,4 @@ using namespace llvm;
|
||||
MSP430TargetAsmInfo::MSP430TargetAsmInfo(const TargetMachine &TM)
|
||||
: ELFTargetAsmInfo(TM) {
|
||||
AlignmentIsInBytes = false;
|
||||
|
||||
BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS);
|
||||
}
|
||||
|
@ -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() &&
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -21,4 +21,5 @@ add_llvm_target(PIC16
|
||||
PIC16Subtarget.cpp
|
||||
PIC16TargetAsmInfo.cpp
|
||||
PIC16TargetMachine.cpp
|
||||
PIC16TargetObjectFile.cpp
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>();
|
||||
|
||||
|
@ -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_;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
401
lib/Target/PIC16/PIC16TargetObjectFile.cpp
Normal file
401
lib/Target/PIC16/PIC16TargetObjectFile.cpp
Normal 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_;
|
||||
}
|
||||
|
100
lib/Target/PIC16/PIC16TargetObjectFile.h
Normal file
100
lib/Target/PIC16/PIC16TargetObjectFile.h
Normal 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
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() &&
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() &&
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
647
lib/Target/TargetLoweringObjectFile.cpp
Normal file
647
lib/Target/TargetLoweringObjectFile.cpp
Normal 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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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!");
|
||||
|
@ -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();
|
||||
|
@ -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'";
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -20,4 +20,5 @@ add_llvm_target(XCore
|
||||
XCoreSubtarget.cpp
|
||||
XCoreTargetAsmInfo.cpp
|
||||
XCoreTargetMachine.cpp
|
||||
XCoreTargetObjectFile.cpp
|
||||
)
|
||||
|
@ -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";
|
||||
|
@ -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()) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
32
lib/Target/XCore/XCoreTargetObjectFile.cpp
Normal file
32
lib/Target/XCore/XCoreTargetObjectFile.cpp
Normal 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);
|
||||
}
|
25
lib/Target/XCore/XCoreTargetObjectFile.h
Normal file
25
lib/Target/XCore/XCoreTargetObjectFile.h
Normal 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
|
Loading…
Reference in New Issue
Block a user