X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FTargetAsmInfo.cpp;h=6fa5420120f517ef042d85b63792079a7548b4f7;hb=fe167c5a145d00a35b980993a514f9056eeefed8;hp=5b7ddbfa4a7eaac929b0f80833f53e44d0bb4d67;hpb=e2cf37b88c089a71727b3ecd466856f0cd638813;p=oota-llvm.git diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 5b7ddbfa4a7..6fa5420120f 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- TargetAsmInfo.cpp - Asm Info ---------------------------------------==// +//===-- llvm/Target/TargetAsmInfo.cpp - Target Assembly Info --------------===// // // The LLVM Compiler Infrastructure // @@ -6,454 +6,22 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take. -// -//===----------------------------------------------------------------------===// -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalVariable.h" -#include "llvm/Function.h" -#include "llvm/Module.h" -#include "llvm/Type.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; -TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) -: TM(tm) { - BSSSection = "\t.bss"; - BSSSection_ = 0; - ReadOnlySection = 0; - SmallDataSection = 0; - SmallBSSSection = 0; - SmallRODataSection = 0; - TLSDataSection = 0; - TLSBSSSection = 0; - ZeroFillDirective = 0; - NonexecutableStackDirective = 0; - NeedsSet = false; - MaxInstLength = 4; - PCSymbol = "$"; - SeparatorChar = ';'; - CommentColumn = 60; - CommentString = "#"; - FirstOperandColumn = 0; - MaxOperandLength = 0; - GlobalPrefix = ""; - PrivateGlobalPrefix = "."; - LessPrivateGlobalPrefix = ""; - JumpTableSpecialLabelPrefix = 0; - GlobalVarAddrPrefix = ""; - GlobalVarAddrSuffix = ""; - FunctionAddrPrefix = ""; - FunctionAddrSuffix = ""; - PersonalityPrefix = ""; - PersonalitySuffix = ""; - NeedsIndirectEncoding = false; - InlineAsmStart = "#APP"; - InlineAsmEnd = "#NO_APP"; - AssemblerDialect = 0; - AllowQuotesInName = false; - ZeroDirective = "\t.zero\t"; - ZeroDirectiveSuffix = 0; - AsciiDirective = "\t.ascii\t"; - AscizDirective = "\t.asciz\t"; - Data8bitsDirective = "\t.byte\t"; - Data16bitsDirective = "\t.short\t"; - Data32bitsDirective = "\t.long\t"; - Data64bitsDirective = "\t.quad\t"; - AlignDirective = "\t.align\t"; - AlignmentIsInBytes = true; - TextAlignFillValue = 0; - SwitchToSectionDirective = "\t.section\t"; - TextSectionStartSuffix = ""; - DataSectionStartSuffix = ""; - SectionEndDirectiveSuffix = 0; - ConstantPoolSection = "\t.section .rodata"; - 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"; - GlobalDirective = "\t.globl\t"; - SetDirective = 0; - LCOMMDirective = 0; - COMMDirective = "\t.comm\t"; - COMMDirectiveTakesAlignment = true; - HasDotTypeDotSizeDirective = true; - HasSingleParameterDotFile = true; - UsedDirective = 0; - WeakRefDirective = 0; - WeakDefDirective = 0; - // FIXME: These are ELFish - move to ELFTAI. - HiddenDirective = "\t.hidden\t"; - ProtectedDirective = "\t.protected\t"; - AbsoluteDebugSectionOffsets = false; - AbsoluteEHSectionOffsets = false; - HasLEB128 = false; - HasDotLocAndDotFile = false; - SupportsDebugInformation = false; - SupportsExceptionHandling = false; - DwarfRequiresFrameSection = true; - DwarfUsesInlineInfoSection = false; - Is_EHSymbolPrivate = true; - GlobalEHDirective = 0; - SupportsWeakOmittedEHFrame = true; - DwarfSectionOffsetDirective = 0; - DwarfAbbrevSection = ".debug_abbrev"; - DwarfInfoSection = ".debug_info"; - DwarfLineSection = ".debug_line"; - DwarfFrameSection = ".debug_frame"; - DwarfPubNamesSection = ".debug_pubnames"; - DwarfPubTypesSection = ".debug_pubtypes"; - DwarfDebugInlineSection = ".debug_inlined"; - DwarfStrSection = ".debug_str"; - DwarfLocSection = ".debug_loc"; - DwarfARangesSection = ".debug_aranges"; - DwarfRangesSection = ".debug_ranges"; - DwarfMacroInfoSection = ".debug_macinfo"; - DwarfEHFrameSection = ".eh_frame"; - DwarfExceptionSection = ".gcc_except_table"; - AsmTransCBE = 0; - TextSection = getUnnamedSection("\t.text", SectionFlags::Code); - DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable); -} - -TargetAsmInfo::~TargetAsmInfo() { -} - -/// Measure the specified inline asm to determine an approximation of its -/// length. -/// Comments (which run till the next SeparatorChar or newline) do not -/// count as an instruction. -/// Any other non-whitespace text is considered an instruction, with -/// multiple instructions separated by SeparatorChar or newlines. -/// Variable-length instructions are not handled here; this function -/// may be overloaded in the target code to do that. -unsigned TargetAsmInfo::getInlineAsmLength(const char *Str) const { - // Count the number of instructions in the asm. - bool atInsnStart = true; - unsigned Length = 0; - for (; *Str; ++Str) { - if (*Str == '\n' || *Str == SeparatorChar) - atInsnStart = true; - if (atInsnStart && !isspace(*Str)) { - Length += MaxInstLength; - atInsnStart = false; - } - if (atInsnStart && strncmp(Str, CommentString, strlen(CommentString))==0) - atInsnStart = false; - } - - return Length; -} - -unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason, - bool Global) const { - return dwarf::DW_EH_PE_absptr; -} - -static bool isSuitableForBSS(const GlobalVariable *GV) { - if (!GV->hasInitializer()) - return true; - - // Leave constant zeros in readonly constant sections, so they can be shared - Constant *C = GV->getInitializer(); - return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS); -} - -static bool isConstantString(const Constant *C) { - // First check: is we have constant array of i8 terminated with zero - const ConstantArray *CVA = dyn_cast(C); - // Check, if initializer is a null-terminated string - if (CVA && CVA->isCString()) - return true; - - // Another possibility: [1 x i8] zeroinitializer - if (isa(C)) { - if (const ArrayType *Ty = dyn_cast(C->getType())) { - return (Ty->getElementType() == Type::Int8Ty && - Ty->getNumElements() == 1); - } - } - - return false; -} - -unsigned TargetAsmInfo::RelocBehaviour() const { - // By default - all relocations in PIC mode would force symbol to be - // placed in r/w section. - return (TM.getRelocationModel() != Reloc::Static ? - Reloc::LocalOrGlobal : Reloc::None); -} - -SectionKind::Kind -TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const { - // Early exit - functions should be always in text sections. - if (isa(GV)) - return SectionKind::Text; - - const GlobalVariable* GVar = dyn_cast(GV); - bool isThreadLocal = GVar->isThreadLocal(); - assert(GVar && "Invalid global value for section selection"); - - if (isSuitableForBSS(GVar)) { - // Variable can be easily put to BSS section. - return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS); - } else if (GVar->isConstant() && !isThreadLocal) { - // Now we know, that varible has initializer and it is constant. We need to - // check its initializer to decide, which section to output it into. Also - // note, there is no thread-local r/o section. - Constant *C = GVar->getInitializer(); - if (C->ContainsRelocations(Reloc::LocalOrGlobal)) { - // Decide, whether it is still possible to put symbol into r/o section. - unsigned Reloc = RelocBehaviour(); - - // We already did a query for 'all' relocs, thus - early exits. - if (Reloc == Reloc::LocalOrGlobal) - return SectionKind::Data; - else if (Reloc == Reloc::None) - return SectionKind::ROData; - else { - // Ok, target wants something funny. Honour it. - return (C->ContainsRelocations(Reloc) ? - SectionKind::Data : SectionKind::ROData); - } - } else { - // Check, if initializer is a null-terminated string - if (isConstantString(C)) - return SectionKind::RODataMergeStr; - else - return SectionKind::RODataMergeConst; - } - } - - // Variable either is not constant or thread-local - output to data section. - return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data); -} - -unsigned -TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV, - const char* Name) const { - unsigned Flags = SectionFlags::None; - - // Decode flags from global itself. - if (GV) { - SectionKind::Kind Kind = SectionKindForGlobal(GV); - switch (Kind) { - case SectionKind::Text: - Flags |= SectionFlags::Code; - break; - case SectionKind::ThreadData: - case SectionKind::ThreadBSS: - Flags |= SectionFlags::TLS; - // FALLS THROUGH - case SectionKind::Data: - case SectionKind::DataRel: - case SectionKind::DataRelLocal: - case SectionKind::DataRelRO: - case SectionKind::DataRelROLocal: - case SectionKind::BSS: - Flags |= SectionFlags::Writeable; - break; - case SectionKind::ROData: - case SectionKind::RODataMergeStr: - case SectionKind::RODataMergeConst: - // No additional flags here - break; - case SectionKind::SmallData: - case SectionKind::SmallBSS: - Flags |= SectionFlags::Writeable; - // FALLS THROUGH - case SectionKind::SmallROData: - Flags |= SectionFlags::Small; - break; - default: - llvm_unreachable("Unexpected section kind!"); - } - - if (GV->isWeakForLinker()) - Flags |= SectionFlags::Linkonce; - } - - // Add flags from sections, if any. - if (Name && *Name) { - Flags |= SectionFlags::Named; - - // 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) - Flags |= SectionFlags::BSS; - else if (strcmp(Name, ".tdata") == 0 || - strncmp(Name, ".tdata.", 7) == 0 || - strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.td.", 18) == 0) - Flags |= SectionFlags::TLS; - else if (strcmp(Name, ".tbss") == 0 || - strncmp(Name, ".tbss.", 6) == 0 || - strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || - strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) - Flags |= SectionFlags::BSS | SectionFlags::TLS; - } - - return Flags; -} - -const Section* -TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { - const Section* S; - // Select section name - if (GV->hasSection()) { - // Honour section already set, if any - unsigned Flags = SectionFlagsForGlobal(GV, - GV->getSection().c_str()); - S = getNamedSection(GV->getSection().c_str(), Flags); - } else { - // Use default section depending on the 'type' of global - S = SelectSectionForGlobal(GV); - } - - return S; -} - -// Lame default implementation. Calculate the section name for global. -const Section* -TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const { - SectionKind::Kind Kind = SectionKindForGlobal(GV); - - if (GV->isWeakForLinker()) { - std::string Name = UniqueSectionForGlobal(GV, Kind); - unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str()); - return getNamedSection(Name.c_str(), Flags); - } else { - if (Kind == SectionKind::Text) - return getTextSection(); - else if (isBSS(Kind) && getBSSSection_()) - return getBSSSection_(); - else if (getReadOnlySection() && SectionKind::isReadOnly(Kind)) - return getReadOnlySection(); - } - - return getDataSection(); -} - -// Lame default implementation. Calculate the section name for machine const. -const Section* -TargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const { - // FIXME: Support data.rel stuff someday - return getDataSection(); -} - -std::string -TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV, - SectionKind::Kind Kind) const { - switch (Kind) { - case SectionKind::Text: - return ".gnu.linkonce.t." + GV->getName(); - case SectionKind::Data: - return ".gnu.linkonce.d." + GV->getName(); - case SectionKind::DataRel: - return ".gnu.linkonce.d.rel" + GV->getName(); - case SectionKind::DataRelLocal: - return ".gnu.linkonce.d.rel.local" + GV->getName(); - case SectionKind::DataRelRO: - return ".gnu.linkonce.d.rel.ro" + GV->getName(); - case SectionKind::DataRelROLocal: - return ".gnu.linkonce.d.rel.ro.local" + GV->getName(); - case SectionKind::SmallData: - return ".gnu.linkonce.s." + GV->getName(); - case SectionKind::BSS: - return ".gnu.linkonce.b." + GV->getName(); - case SectionKind::SmallBSS: - return ".gnu.linkonce.sb." + GV->getName(); - case SectionKind::ROData: - case SectionKind::RODataMergeConst: - case SectionKind::RODataMergeStr: - return ".gnu.linkonce.r." + GV->getName(); - case SectionKind::SmallROData: - return ".gnu.linkonce.s2." + GV->getName(); - case SectionKind::ThreadData: - return ".gnu.linkonce.td." + GV->getName(); - case SectionKind::ThreadBSS: - return ".gnu.linkonce.tb." + GV->getName(); - default: - llvm_unreachable("Unknown section kind"); - } - return NULL; -} - -const Section* -TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags, - bool Override) const { - Section& S = Sections[Name]; - - // This is newly-created section, set it up properly. - if (S.Flags == SectionFlags::Invalid || Override) { - S.Flags = Flags | SectionFlags::Named; - S.Name = Name; - } - - return &S; -} - -const Section* -TargetAsmInfo::getUnnamedSection(const char *Directive, unsigned Flags, - bool Override) const { - Section& S = Sections[Directive]; - - // This is newly-created section, set it up properly. - if (S.Flags == SectionFlags::Invalid || Override) { - S.Flags = Flags & ~SectionFlags::Named; - S.Name = Directive; - } - - return &S; -} - -const std::string& -TargetAsmInfo::getSectionFlags(unsigned Flags) const { - SectionFlags::FlagsStringsMapType::iterator I = FlagsStrings.find(Flags); - - // We didn't print these flags yet, print and save them to map. This reduces - // amount of heap trashing due to std::string construction / concatenation. - if (I == FlagsStrings.end()) - I = FlagsStrings.insert(std::make_pair(Flags, - printSectionFlags(Flags))).first; - - return I->second; -} - -unsigned TargetAsmInfo::getULEB128Size(unsigned Value) { - unsigned Size = 0; - do { - Value >>= 7; - Size += sizeof(int8_t); - } while (Value); - return Size; -} - -unsigned TargetAsmInfo::getSLEB128Size(int Value) { - unsigned Size = 0; - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - unsigned Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - Size += sizeof(int8_t); - } while (IsMore); - return Size; +TargetAsmInfo::TargetAsmInfo(const TargetMachine &TM) { + TLOF = &TM.getTargetLowering()->getObjFileLowering(); + const TargetData &TD = *TM.getTargetData(); + IsLittleEndian = TD.isLittleEndian(); + PointerSize = TD.getPointerSize(); + const TargetFrameLowering &TFI = *TM.getFrameLowering(); + StackDir = TFI.getStackGrowthDirection(); + TRI = TM.getRegisterInfo(); + TFI.getInitialFrameState(InitialFrameState); }