| Jim Laskey | 7c95ad4 | 2006-09-06 19:21:41 +0000 | [diff] [blame] | 1 | //===-- TargetAsmInfo.cpp - Asm Info ---------------------------------------==// | 
| Jim Laskey | ec0d9fe | 2006-09-06 18:35:33 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | 4ee451d | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Jim Laskey | ec0d9fe | 2006-09-06 18:35:33 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines target asm properties related what form asm statements | 
|  | 11 | // should take. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 15 | #include "llvm/Constants.h" | 
| Anton Korobeynikov | 72bb402 | 2009-01-27 22:29:24 +0000 | [diff] [blame] | 16 | #include "llvm/DerivedTypes.h" | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 17 | #include "llvm/GlobalVariable.h" | 
|  | 18 | #include "llvm/Function.h" | 
|  | 19 | #include "llvm/Module.h" | 
|  | 20 | #include "llvm/Type.h" | 
| Jim Laskey | ec0d9fe | 2006-09-06 18:35:33 +0000 | [diff] [blame] | 21 | #include "llvm/Target/TargetAsmInfo.h" | 
| Anton Korobeynikov | db23231 | 2009-03-29 17:13:49 +0000 | [diff] [blame] | 22 | #include "llvm/Target/TargetMachine.h" | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 23 | #include "llvm/Target/TargetOptions.h" | 
| Anton Korobeynikov | cee750f | 2008-02-27 23:33:50 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Dwarf.h" | 
| Torok Edwin | c25e758 | 2009-07-11 20:10:48 +0000 | [diff] [blame] | 25 | #include "llvm/Support/ErrorHandling.h" | 
| Dale Johannesen | 3bb6283 | 2007-04-23 20:00:17 +0000 | [diff] [blame] | 26 | #include <cctype> | 
|  | 27 | #include <cstring> | 
| Jim Laskey | ec0d9fe | 2006-09-06 18:35:33 +0000 | [diff] [blame] | 28 | using namespace llvm; | 
|  | 29 |  | 
| Chris Lattner | 4e0f25b | 2009-06-19 00:08:39 +0000 | [diff] [blame] | 30 | TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) | 
|  | 31 | : TM(tm) { | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 32 | BSSSection = "\t.bss"; | 
|  | 33 | BSSSection_ = 0; | 
|  | 34 | ReadOnlySection = 0; | 
|  | 35 | SmallDataSection = 0; | 
|  | 36 | SmallBSSSection = 0; | 
|  | 37 | SmallRODataSection = 0; | 
|  | 38 | TLSDataSection = 0; | 
|  | 39 | TLSBSSSection = 0; | 
|  | 40 | ZeroFillDirective = 0; | 
|  | 41 | NonexecutableStackDirective = 0; | 
|  | 42 | NeedsSet = false; | 
|  | 43 | MaxInstLength = 4; | 
|  | 44 | PCSymbol = "$"; | 
|  | 45 | SeparatorChar = ';'; | 
| David Greene | 014700c | 2009-07-13 20:25:48 +0000 | [diff] [blame] | 46 | CommentColumn = 60; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 47 | CommentString = "#"; | 
| David Greene | ab9238e | 2009-07-17 14:24:46 +0000 | [diff] [blame] | 48 | FirstOperandColumn = 0; | 
|  | 49 | MaxOperandLength = 0; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 50 | GlobalPrefix = ""; | 
|  | 51 | PrivateGlobalPrefix = "."; | 
|  | 52 | LessPrivateGlobalPrefix = ""; | 
|  | 53 | JumpTableSpecialLabelPrefix = 0; | 
|  | 54 | GlobalVarAddrPrefix = ""; | 
|  | 55 | GlobalVarAddrSuffix = ""; | 
|  | 56 | FunctionAddrPrefix = ""; | 
|  | 57 | FunctionAddrSuffix = ""; | 
|  | 58 | PersonalityPrefix = ""; | 
|  | 59 | PersonalitySuffix = ""; | 
|  | 60 | NeedsIndirectEncoding = false; | 
|  | 61 | InlineAsmStart = "#APP"; | 
|  | 62 | InlineAsmEnd = "#NO_APP"; | 
|  | 63 | AssemblerDialect = 0; | 
| Chris Lattner | a93ca92 | 2009-06-18 23:41:35 +0000 | [diff] [blame] | 64 | AllowQuotesInName = false; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 65 | ZeroDirective = "\t.zero\t"; | 
|  | 66 | ZeroDirectiveSuffix = 0; | 
|  | 67 | AsciiDirective = "\t.ascii\t"; | 
|  | 68 | AscizDirective = "\t.asciz\t"; | 
|  | 69 | Data8bitsDirective = "\t.byte\t"; | 
|  | 70 | Data16bitsDirective = "\t.short\t"; | 
|  | 71 | Data32bitsDirective = "\t.long\t"; | 
|  | 72 | Data64bitsDirective = "\t.quad\t"; | 
|  | 73 | AlignDirective = "\t.align\t"; | 
|  | 74 | AlignmentIsInBytes = true; | 
|  | 75 | TextAlignFillValue = 0; | 
|  | 76 | SwitchToSectionDirective = "\t.section\t"; | 
|  | 77 | TextSectionStartSuffix = ""; | 
|  | 78 | DataSectionStartSuffix = ""; | 
|  | 79 | SectionEndDirectiveSuffix = 0; | 
|  | 80 | ConstantPoolSection = "\t.section .rodata"; | 
|  | 81 | JumpTableDataSection = "\t.section .rodata"; | 
|  | 82 | JumpTableDirective = 0; | 
|  | 83 | CStringSection = 0; | 
|  | 84 | CStringSection_ = 0; | 
|  | 85 | // FIXME: Flags are ELFish - replace with normal section stuff. | 
|  | 86 | StaticCtorsSection = "\t.section .ctors,\"aw\",@progbits"; | 
|  | 87 | StaticDtorsSection = "\t.section .dtors,\"aw\",@progbits"; | 
|  | 88 | GlobalDirective = "\t.globl\t"; | 
|  | 89 | SetDirective = 0; | 
|  | 90 | LCOMMDirective = 0; | 
|  | 91 | COMMDirective = "\t.comm\t"; | 
|  | 92 | COMMDirectiveTakesAlignment = true; | 
|  | 93 | HasDotTypeDotSizeDirective = true; | 
| Rafael Espindola | 952b839 | 2008-12-03 11:01:37 +0000 | [diff] [blame] | 94 | HasSingleParameterDotFile = true; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 95 | UsedDirective = 0; | 
|  | 96 | WeakRefDirective = 0; | 
|  | 97 | WeakDefDirective = 0; | 
|  | 98 | // FIXME: These are ELFish - move to ELFTAI. | 
|  | 99 | HiddenDirective = "\t.hidden\t"; | 
|  | 100 | ProtectedDirective = "\t.protected\t"; | 
|  | 101 | AbsoluteDebugSectionOffsets = false; | 
|  | 102 | AbsoluteEHSectionOffsets = false; | 
|  | 103 | HasLEB128 = false; | 
|  | 104 | HasDotLocAndDotFile = false; | 
|  | 105 | SupportsDebugInformation = false; | 
|  | 106 | SupportsExceptionHandling = false; | 
|  | 107 | DwarfRequiresFrameSection = true; | 
| Devang Patel | 0f7fef3 | 2009-04-13 17:02:03 +0000 | [diff] [blame] | 108 | DwarfUsesInlineInfoSection = false; | 
| Chris Lattner | e2cf37b | 2009-07-17 20:46:40 +0000 | [diff] [blame^] | 109 | Is_EHSymbolPrivate = true; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 110 | GlobalEHDirective = 0; | 
|  | 111 | SupportsWeakOmittedEHFrame = true; | 
|  | 112 | DwarfSectionOffsetDirective = 0; | 
|  | 113 | DwarfAbbrevSection = ".debug_abbrev"; | 
|  | 114 | DwarfInfoSection = ".debug_info"; | 
|  | 115 | DwarfLineSection = ".debug_line"; | 
|  | 116 | DwarfFrameSection = ".debug_frame"; | 
|  | 117 | DwarfPubNamesSection = ".debug_pubnames"; | 
|  | 118 | DwarfPubTypesSection = ".debug_pubtypes"; | 
| Devang Patel | 0f7fef3 | 2009-04-13 17:02:03 +0000 | [diff] [blame] | 119 | DwarfDebugInlineSection = ".debug_inlined"; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 120 | DwarfStrSection = ".debug_str"; | 
|  | 121 | DwarfLocSection = ".debug_loc"; | 
|  | 122 | DwarfARangesSection = ".debug_aranges"; | 
|  | 123 | DwarfRangesSection = ".debug_ranges"; | 
| Chris Lattner | b839c3f | 2009-06-18 23:31:37 +0000 | [diff] [blame] | 124 | DwarfMacroInfoSection = ".debug_macinfo"; | 
| Anton Korobeynikov | 32b952a | 2008-09-25 21:00:33 +0000 | [diff] [blame] | 125 | DwarfEHFrameSection = ".eh_frame"; | 
|  | 126 | DwarfExceptionSection = ".gcc_except_table"; | 
|  | 127 | AsmTransCBE = 0; | 
| Anton Korobeynikov | d7ca416 | 2008-09-24 22:15:21 +0000 | [diff] [blame] | 128 | TextSection = getUnnamedSection("\t.text", SectionFlags::Code); | 
| Anton Korobeynikov | 315690e | 2008-09-24 22:16:16 +0000 | [diff] [blame] | 129 | DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable); | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 130 | } | 
| Chris Lattner | f5b10ec | 2006-10-05 00:35:16 +0000 | [diff] [blame] | 131 |  | 
|  | 132 | TargetAsmInfo::~TargetAsmInfo() { | 
|  | 133 | } | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 134 |  | 
|  | 135 | /// Measure the specified inline asm to determine an approximation of its | 
|  | 136 | /// length. | 
| Dale Johannesen | 3bb6283 | 2007-04-23 20:00:17 +0000 | [diff] [blame] | 137 | /// Comments (which run till the next SeparatorChar or newline) do not | 
|  | 138 | /// count as an instruction. | 
|  | 139 | /// Any other non-whitespace text is considered an instruction, with | 
|  | 140 | /// multiple instructions separated by SeparatorChar or newlines. | 
|  | 141 | /// Variable-length instructions are not handled here; this function | 
|  | 142 | /// may be overloaded in the target code to do that. | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 143 | unsigned TargetAsmInfo::getInlineAsmLength(const char *Str) const { | 
|  | 144 | // Count the number of instructions in the asm. | 
| Dale Johannesen | 3bb6283 | 2007-04-23 20:00:17 +0000 | [diff] [blame] | 145 | bool atInsnStart = true; | 
|  | 146 | unsigned Length = 0; | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 147 | for (; *Str; ++Str) { | 
|  | 148 | if (*Str == '\n' || *Str == SeparatorChar) | 
| Dale Johannesen | 3bb6283 | 2007-04-23 20:00:17 +0000 | [diff] [blame] | 149 | atInsnStart = true; | 
|  | 150 | if (atInsnStart && !isspace(*Str)) { | 
|  | 151 | Length += MaxInstLength; | 
|  | 152 | atInsnStart = false; | 
|  | 153 | } | 
|  | 154 | if (atInsnStart && strncmp(Str, CommentString, strlen(CommentString))==0) | 
|  | 155 | atInsnStart = false; | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 156 | } | 
|  | 157 |  | 
| Dale Johannesen | 3bb6283 | 2007-04-23 20:00:17 +0000 | [diff] [blame] | 158 | return Length; | 
| Chris Lattner | 4c7b07a | 2006-10-13 17:50:07 +0000 | [diff] [blame] | 159 | } | 
| Anton Korobeynikov | a6199c8 | 2007-03-07 02:47:57 +0000 | [diff] [blame] | 160 |  | 
| Anton Korobeynikov | 8213f9c | 2008-02-29 22:09:08 +0000 | [diff] [blame] | 161 | unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason, | 
| Anton Korobeynikov | cee750f | 2008-02-27 23:33:50 +0000 | [diff] [blame] | 162 | bool Global) const { | 
|  | 163 | return dwarf::DW_EH_PE_absptr; | 
|  | 164 | } | 
|  | 165 |  | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 166 | static bool isSuitableForBSS(const GlobalVariable *GV) { | 
|  | 167 | if (!GV->hasInitializer()) | 
|  | 168 | return true; | 
|  | 169 |  | 
|  | 170 | // Leave constant zeros in readonly constant sections, so they can be shared | 
|  | 171 | Constant *C = GV->getInitializer(); | 
|  | 172 | return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS); | 
|  | 173 | } | 
|  | 174 |  | 
| Owen Anderson | 1ca29d3 | 2009-07-13 21:27:19 +0000 | [diff] [blame] | 175 | static bool isConstantString(const Constant *C) { | 
| Anton Korobeynikov | 72bb402 | 2009-01-27 22:29:24 +0000 | [diff] [blame] | 176 | // First check: is we have constant array of i8 terminated with zero | 
|  | 177 | const ConstantArray *CVA = dyn_cast<ConstantArray>(C); | 
|  | 178 | // Check, if initializer is a null-terminated string | 
| Owen Anderson | 1ca29d3 | 2009-07-13 21:27:19 +0000 | [diff] [blame] | 179 | if (CVA && CVA->isCString()) | 
| Anton Korobeynikov | 72bb402 | 2009-01-27 22:29:24 +0000 | [diff] [blame] | 180 | return true; | 
|  | 181 |  | 
|  | 182 | // Another possibility: [1 x i8] zeroinitializer | 
|  | 183 | if (isa<ConstantAggregateZero>(C)) { | 
|  | 184 | if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) { | 
|  | 185 | return (Ty->getElementType() == Type::Int8Ty && | 
|  | 186 | Ty->getNumElements() == 1); | 
|  | 187 | } | 
|  | 188 | } | 
|  | 189 |  | 
|  | 190 | return false; | 
|  | 191 | } | 
|  | 192 |  | 
| Anton Korobeynikov | db23231 | 2009-03-29 17:13:49 +0000 | [diff] [blame] | 193 | unsigned TargetAsmInfo::RelocBehaviour() const { | 
|  | 194 | // By default - all relocations in PIC mode would force symbol to be | 
|  | 195 | // placed in r/w section. | 
|  | 196 | return (TM.getRelocationModel() != Reloc::Static ? | 
|  | 197 | Reloc::LocalOrGlobal : Reloc::None); | 
|  | 198 | } | 
| Anton Korobeynikov | 72bb402 | 2009-01-27 22:29:24 +0000 | [diff] [blame] | 199 |  | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 200 | SectionKind::Kind | 
|  | 201 | TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const { | 
|  | 202 | // Early exit - functions should be always in text sections. | 
|  | 203 | if (isa<Function>(GV)) | 
|  | 204 | return SectionKind::Text; | 
|  | 205 |  | 
|  | 206 | const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV); | 
|  | 207 | bool isThreadLocal = GVar->isThreadLocal(); | 
|  | 208 | assert(GVar && "Invalid global value for section selection"); | 
|  | 209 |  | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 210 | if (isSuitableForBSS(GVar)) { | 
|  | 211 | // Variable can be easily put to BSS section. | 
|  | 212 | return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS); | 
|  | 213 | } else if (GVar->isConstant() && !isThreadLocal) { | 
|  | 214 | // Now we know, that varible has initializer and it is constant. We need to | 
|  | 215 | // check its initializer to decide, which section to output it into. Also | 
|  | 216 | // note, there is no thread-local r/o section. | 
|  | 217 | Constant *C = GVar->getInitializer(); | 
| Anton Korobeynikov | db23231 | 2009-03-29 17:13:49 +0000 | [diff] [blame] | 218 | if (C->ContainsRelocations(Reloc::LocalOrGlobal)) { | 
|  | 219 | // Decide, whether it is still possible to put symbol into r/o section. | 
|  | 220 | unsigned Reloc = RelocBehaviour(); | 
|  | 221 |  | 
|  | 222 | // We already did a query for 'all' relocs, thus - early exits. | 
| Anton Korobeynikov | fca82de | 2009-03-30 15:27:43 +0000 | [diff] [blame] | 223 | if (Reloc == Reloc::LocalOrGlobal) | 
|  | 224 | return SectionKind::Data; | 
|  | 225 | else if (Reloc == Reloc::None) | 
| Anton Korobeynikov | db23231 | 2009-03-29 17:13:49 +0000 | [diff] [blame] | 226 | return SectionKind::ROData; | 
|  | 227 | else { | 
|  | 228 | // Ok, target wants something funny. Honour it. | 
| Anton Korobeynikov | fca82de | 2009-03-30 15:27:43 +0000 | [diff] [blame] | 229 | return (C->ContainsRelocations(Reloc) ? | 
|  | 230 | SectionKind::Data : SectionKind::ROData); | 
| Anton Korobeynikov | db23231 | 2009-03-29 17:13:49 +0000 | [diff] [blame] | 231 | } | 
|  | 232 | } else { | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 233 | // Check, if initializer is a null-terminated string | 
| Owen Anderson | 1ca29d3 | 2009-07-13 21:27:19 +0000 | [diff] [blame] | 234 | if (isConstantString(C)) | 
| Anton Korobeynikov | 0e48a0c | 2008-07-09 13:24:38 +0000 | [diff] [blame] | 235 | return SectionKind::RODataMergeStr; | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 236 | else | 
| Anton Korobeynikov | 0e48a0c | 2008-07-09 13:24:38 +0000 | [diff] [blame] | 237 | return SectionKind::RODataMergeConst; | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 238 | } | 
|  | 239 | } | 
|  | 240 |  | 
| Anton Korobeynikov | 71a7c6c | 2009-03-30 15:27:03 +0000 | [diff] [blame] | 241 | // Variable either is not constant or thread-local - output to data section. | 
| Anton Korobeynikov | fca82de | 2009-03-30 15:27:43 +0000 | [diff] [blame] | 242 | return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data); | 
| Anton Korobeynikov | 28a2b54 | 2008-06-28 13:45:57 +0000 | [diff] [blame] | 243 | } | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 244 |  | 
|  | 245 | unsigned | 
|  | 246 | TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV, | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 247 | const char* Name) const { | 
|  | 248 | unsigned Flags = SectionFlags::None; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 249 |  | 
|  | 250 | // Decode flags from global itself. | 
|  | 251 | if (GV) { | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 252 | SectionKind::Kind Kind = SectionKindForGlobal(GV); | 
|  | 253 | switch (Kind) { | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 254 | case SectionKind::Text: | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 255 | Flags |= SectionFlags::Code; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 256 | break; | 
|  | 257 | case SectionKind::ThreadData: | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 258 | case SectionKind::ThreadBSS: | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 259 | Flags |= SectionFlags::TLS; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 260 | // FALLS THROUGH | 
| Anton Korobeynikov | 7d51edf | 2008-07-09 13:29:44 +0000 | [diff] [blame] | 261 | case SectionKind::Data: | 
| Anton Korobeynikov | 71a7c6c | 2009-03-30 15:27:03 +0000 | [diff] [blame] | 262 | case SectionKind::DataRel: | 
|  | 263 | case SectionKind::DataRelLocal: | 
|  | 264 | case SectionKind::DataRelRO: | 
|  | 265 | case SectionKind::DataRelROLocal: | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 266 | case SectionKind::BSS: | 
| Anton Korobeynikov | 7d51edf | 2008-07-09 13:29:44 +0000 | [diff] [blame] | 267 | Flags |= SectionFlags::Writeable; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 268 | break; | 
|  | 269 | case SectionKind::ROData: | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 270 | case SectionKind::RODataMergeStr: | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 271 | case SectionKind::RODataMergeConst: | 
| Anton Korobeynikov | 7d51edf | 2008-07-09 13:29:44 +0000 | [diff] [blame] | 272 | // No additional flags here | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 273 | break; | 
| Anton Korobeynikov | 04dda73 | 2008-07-22 17:09:59 +0000 | [diff] [blame] | 274 | case SectionKind::SmallData: | 
|  | 275 | case SectionKind::SmallBSS: | 
|  | 276 | Flags |= SectionFlags::Writeable; | 
|  | 277 | // FALLS THROUGH | 
|  | 278 | case SectionKind::SmallROData: | 
|  | 279 | Flags |= SectionFlags::Small; | 
|  | 280 | break; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 281 | default: | 
| Torok Edwin | c23197a | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 282 | llvm_unreachable("Unexpected section kind!"); | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 283 | } | 
|  | 284 |  | 
| Duncan Sands | 667d4b8 | 2009-03-07 15:45:40 +0000 | [diff] [blame] | 285 | if (GV->isWeakForLinker()) | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 286 | Flags |= SectionFlags::Linkonce; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 287 | } | 
|  | 288 |  | 
|  | 289 | // Add flags from sections, if any. | 
| Anton Korobeynikov | 2a88917 | 2008-07-09 13:25:46 +0000 | [diff] [blame] | 290 | if (Name && *Name) { | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 291 | Flags |= SectionFlags::Named; | 
|  | 292 |  | 
|  | 293 | // Some lame default implementation based on some magic section names. | 
|  | 294 | if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 || | 
| Anton Korobeynikov | 04dda73 | 2008-07-22 17:09:59 +0000 | [diff] [blame] | 295 | strncmp(Name, ".llvm.linkonce.b.", 17) == 0 || | 
|  | 296 | strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || | 
|  | 297 | strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 298 | Flags |= SectionFlags::BSS; | 
|  | 299 | else if (strcmp(Name, ".tdata") == 0 || | 
|  | 300 | strncmp(Name, ".tdata.", 7) == 0 || | 
|  | 301 | strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || | 
|  | 302 | strncmp(Name, ".llvm.linkonce.td.", 18) == 0) | 
|  | 303 | Flags |= SectionFlags::TLS; | 
|  | 304 | else if (strcmp(Name, ".tbss") == 0 || | 
|  | 305 | strncmp(Name, ".tbss.", 6) == 0 || | 
|  | 306 | strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || | 
|  | 307 | strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) | 
|  | 308 | Flags |= SectionFlags::BSS | SectionFlags::TLS; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 309 | } | 
|  | 310 |  | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 311 | return Flags; | 
| Anton Korobeynikov | beb9d40 | 2008-07-09 13:16:59 +0000 | [diff] [blame] | 312 | } | 
| Anton Korobeynikov | 0c60246 | 2008-07-09 13:18:02 +0000 | [diff] [blame] | 313 |  | 
| Anton Korobeynikov | c25e1ea | 2008-09-24 22:14:23 +0000 | [diff] [blame] | 314 | const Section* | 
| Evan Cheng | 42ccc21 | 2008-08-08 17:56:50 +0000 | [diff] [blame] | 315 | TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 316 | const Section* S; | 
| Anton Korobeynikov | 265c525 | 2008-07-09 13:22:46 +0000 | [diff] [blame] | 317 | // Select section name | 
|  | 318 | if (GV->hasSection()) { | 
|  | 319 | // Honour section already set, if any | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 320 | unsigned Flags = SectionFlagsForGlobal(GV, | 
|  | 321 | GV->getSection().c_str()); | 
|  | 322 | S = getNamedSection(GV->getSection().c_str(), Flags); | 
| Anton Korobeynikov | 265c525 | 2008-07-09 13:22:46 +0000 | [diff] [blame] | 323 | } else { | 
|  | 324 | // Use default section depending on the 'type' of global | 
| Evan Cheng | 42ccc21 | 2008-08-08 17:56:50 +0000 | [diff] [blame] | 325 | S = SelectSectionForGlobal(GV); | 
| Anton Korobeynikov | 265c525 | 2008-07-09 13:22:46 +0000 | [diff] [blame] | 326 | } | 
|  | 327 |  | 
| Anton Korobeynikov | c25e1ea | 2008-09-24 22:14:23 +0000 | [diff] [blame] | 328 | return S; | 
| Anton Korobeynikov | 265c525 | 2008-07-09 13:22:46 +0000 | [diff] [blame] | 329 | } | 
|  | 330 |  | 
|  | 331 | // Lame default implementation. Calculate the section name for global. | 
| Evan Cheng | 42ccc21 | 2008-08-08 17:56:50 +0000 | [diff] [blame] | 332 | const Section* | 
|  | 333 | TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const { | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 334 | SectionKind::Kind Kind = SectionKindForGlobal(GV); | 
| Anton Korobeynikov | 0c60246 | 2008-07-09 13:18:02 +0000 | [diff] [blame] | 335 |  | 
| Duncan Sands | 667d4b8 | 2009-03-07 15:45:40 +0000 | [diff] [blame] | 336 | if (GV->isWeakForLinker()) { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 337 | std::string Name = UniqueSectionForGlobal(GV, Kind); | 
|  | 338 | unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str()); | 
|  | 339 | return getNamedSection(Name.c_str(), Flags); | 
|  | 340 | } else { | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 341 | if (Kind == SectionKind::Text) | 
| Anton Korobeynikov | d7ca416 | 2008-09-24 22:15:21 +0000 | [diff] [blame] | 342 | return getTextSection(); | 
| Anton Korobeynikov | 4578862 | 2008-08-07 09:51:54 +0000 | [diff] [blame] | 343 | else if (isBSS(Kind) && getBSSSection_()) | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 344 | return getBSSSection_(); | 
| Anton Korobeynikov | 00181a3 | 2008-09-24 22:20:27 +0000 | [diff] [blame] | 345 | else if (getReadOnlySection() && SectionKind::isReadOnly(Kind)) | 
|  | 346 | return getReadOnlySection(); | 
| Anton Korobeynikov | 265c525 | 2008-07-09 13:22:46 +0000 | [diff] [blame] | 347 | } | 
| Anton Korobeynikov | 0c60246 | 2008-07-09 13:18:02 +0000 | [diff] [blame] | 348 |  | 
| Anton Korobeynikov | 315690e | 2008-09-24 22:16:16 +0000 | [diff] [blame] | 349 | return getDataSection(); | 
| Anton Korobeynikov | 0c60246 | 2008-07-09 13:18:02 +0000 | [diff] [blame] | 350 | } | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 351 |  | 
| Anton Korobeynikov | 93cacf1 | 2008-08-07 09:50:34 +0000 | [diff] [blame] | 352 | // Lame default implementation. Calculate the section name for machine const. | 
|  | 353 | const Section* | 
|  | 354 | TargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const { | 
|  | 355 | // FIXME: Support data.rel stuff someday | 
| Anton Korobeynikov | 315690e | 2008-09-24 22:16:16 +0000 | [diff] [blame] | 356 | return getDataSection(); | 
| Anton Korobeynikov | 93cacf1 | 2008-08-07 09:50:34 +0000 | [diff] [blame] | 357 | } | 
|  | 358 |  | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 359 | std::string | 
|  | 360 | TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV, | 
| Anton Korobeynikov | b20015b | 2008-07-09 13:25:26 +0000 | [diff] [blame] | 361 | SectionKind::Kind Kind) const { | 
|  | 362 | switch (Kind) { | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 363 | case SectionKind::Text: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 364 | return ".gnu.linkonce.t." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 365 | case SectionKind::Data: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 366 | return ".gnu.linkonce.d." + GV->getName(); | 
| Anton Korobeynikov | 71a7c6c | 2009-03-30 15:27:03 +0000 | [diff] [blame] | 367 | case SectionKind::DataRel: | 
|  | 368 | return ".gnu.linkonce.d.rel" + GV->getName(); | 
|  | 369 | case SectionKind::DataRelLocal: | 
|  | 370 | return ".gnu.linkonce.d.rel.local" + GV->getName(); | 
|  | 371 | case SectionKind::DataRelRO: | 
|  | 372 | return ".gnu.linkonce.d.rel.ro" + GV->getName(); | 
|  | 373 | case SectionKind::DataRelROLocal: | 
|  | 374 | return ".gnu.linkonce.d.rel.ro.local" + GV->getName(); | 
| Anton Korobeynikov | 04dda73 | 2008-07-22 17:09:59 +0000 | [diff] [blame] | 375 | case SectionKind::SmallData: | 
|  | 376 | return ".gnu.linkonce.s." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 377 | case SectionKind::BSS: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 378 | return ".gnu.linkonce.b." + GV->getName(); | 
| Anton Korobeynikov | 04dda73 | 2008-07-22 17:09:59 +0000 | [diff] [blame] | 379 | case SectionKind::SmallBSS: | 
|  | 380 | return ".gnu.linkonce.sb." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 381 | case SectionKind::ROData: | 
|  | 382 | case SectionKind::RODataMergeConst: | 
|  | 383 | case SectionKind::RODataMergeStr: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 384 | return ".gnu.linkonce.r." + GV->getName(); | 
| Anton Korobeynikov | 04dda73 | 2008-07-22 17:09:59 +0000 | [diff] [blame] | 385 | case SectionKind::SmallROData: | 
|  | 386 | return ".gnu.linkonce.s2." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 387 | case SectionKind::ThreadData: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 388 | return ".gnu.linkonce.td." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 389 | case SectionKind::ThreadBSS: | 
| Anton Korobeynikov | 5248670 | 2008-07-09 13:24:55 +0000 | [diff] [blame] | 390 | return ".gnu.linkonce.tb." + GV->getName(); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 391 | default: | 
| Torok Edwin | c23197a | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 392 | llvm_unreachable("Unknown section kind"); | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 393 | } | 
| Devang Patel | 8a84e44 | 2009-01-05 17:31:22 +0000 | [diff] [blame] | 394 | return NULL; | 
| Anton Korobeynikov | 29b03f7 | 2008-07-09 13:19:38 +0000 | [diff] [blame] | 395 | } | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 396 |  | 
|  | 397 | const Section* | 
| Anton Korobeynikov | 328da65 | 2008-08-16 12:58:12 +0000 | [diff] [blame] | 398 | TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags, | 
|  | 399 | bool Override) const { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 400 | Section& S = Sections[Name]; | 
|  | 401 |  | 
|  | 402 | // This is newly-created section, set it up properly. | 
| Anton Korobeynikov | 328da65 | 2008-08-16 12:58:12 +0000 | [diff] [blame] | 403 | if (S.Flags == SectionFlags::Invalid || Override) { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 404 | S.Flags = Flags | SectionFlags::Named; | 
|  | 405 | S.Name = Name; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | return &S; | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | const Section* | 
| Anton Korobeynikov | 328da65 | 2008-08-16 12:58:12 +0000 | [diff] [blame] | 412 | TargetAsmInfo::getUnnamedSection(const char *Directive, unsigned Flags, | 
|  | 413 | bool Override) const { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 414 | Section& S = Sections[Directive]; | 
|  | 415 |  | 
|  | 416 | // This is newly-created section, set it up properly. | 
| Anton Korobeynikov | 328da65 | 2008-08-16 12:58:12 +0000 | [diff] [blame] | 417 | if (S.Flags == SectionFlags::Invalid || Override) { | 
| Anton Korobeynikov | 0d44ba8 | 2008-07-09 13:28:49 +0000 | [diff] [blame] | 418 | S.Flags = Flags & ~SectionFlags::Named; | 
|  | 419 | S.Name = Directive; | 
|  | 420 | } | 
|  | 421 |  | 
|  | 422 | return &S; | 
|  | 423 | } | 
| Anton Korobeynikov | d0c1e29 | 2008-08-16 12:57:07 +0000 | [diff] [blame] | 424 |  | 
|  | 425 | const std::string& | 
|  | 426 | TargetAsmInfo::getSectionFlags(unsigned Flags) const { | 
|  | 427 | SectionFlags::FlagsStringsMapType::iterator I = FlagsStrings.find(Flags); | 
|  | 428 |  | 
|  | 429 | // We didn't print these flags yet, print and save them to map. This reduces | 
|  | 430 | // amount of heap trashing due to std::string construction / concatenation. | 
|  | 431 | if (I == FlagsStrings.end()) | 
|  | 432 | I = FlagsStrings.insert(std::make_pair(Flags, | 
|  | 433 | printSectionFlags(Flags))).first; | 
|  | 434 |  | 
|  | 435 | return I->second; | 
|  | 436 | } | 
| Anton Korobeynikov | ffe31d7 | 2008-08-16 12:57:46 +0000 | [diff] [blame] | 437 |  | 
|  | 438 | unsigned TargetAsmInfo::getULEB128Size(unsigned Value) { | 
|  | 439 | unsigned Size = 0; | 
|  | 440 | do { | 
|  | 441 | Value >>= 7; | 
|  | 442 | Size += sizeof(int8_t); | 
|  | 443 | } while (Value); | 
|  | 444 | return Size; | 
|  | 445 | } | 
|  | 446 |  | 
|  | 447 | unsigned TargetAsmInfo::getSLEB128Size(int Value) { | 
|  | 448 | unsigned Size = 0; | 
|  | 449 | int Sign = Value >> (8 * sizeof(Value) - 1); | 
|  | 450 | bool IsMore; | 
|  | 451 |  | 
|  | 452 | do { | 
|  | 453 | unsigned Byte = Value & 0x7f; | 
|  | 454 | Value >>= 7; | 
|  | 455 | IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; | 
|  | 456 | Size += sizeof(int8_t); | 
|  | 457 | } while (IsMore); | 
|  | 458 | return Size; | 
|  | 459 | } |