| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 1 | //===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines target asm properties related what form asm statements | 
|  | 11 | // should take in general on ELF-based targets | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "llvm/Constants.h" | 
|  | 16 | #include "llvm/DerivedTypes.h" | 
|  | 17 | #include "llvm/Function.h" | 
|  | 18 | #include "llvm/GlobalVariable.h" | 
|  | 19 | #include "llvm/ADT/StringExtras.h" | 
| Anton Korobeynikov | ef643a4 | 2008-08-07 09:50:34 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/MachineConstantPool.h" | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 21 | #include "llvm/Target/ELFTargetAsmInfo.h" | 
|  | 22 | #include "llvm/Target/TargetMachine.h" | 
|  | 23 | #include "llvm/Target/TargetData.h" | 
|  | 24 |  | 
|  | 25 | using namespace llvm; | 
|  | 26 |  | 
| Dan Gohman | ac41d9f | 2008-11-03 18:22:42 +0000 | [diff] [blame] | 27 | ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM) | 
|  | 28 | : TargetAsmInfo(TM) { | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 29 |  | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 30 | BSSSection_  = getUnnamedSection("\t.bss", | 
|  | 31 | SectionFlags::Writeable | SectionFlags::BSS); | 
| Anton Korobeynikov | 8e7b939 | 2008-09-24 22:20:27 +0000 | [diff] [blame] | 32 | ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None); | 
| Anton Korobeynikov | 22db305 | 2008-09-24 22:17:06 +0000 | [diff] [blame] | 33 | TLSDataSection = getNamedSection("\t.tdata", | 
|  | 34 | SectionFlags::Writeable | SectionFlags::TLS); | 
|  | 35 | TLSBSSSection = getNamedSection("\t.tbss", | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 36 | SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS); | 
|  | 37 |  | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | const Section* | 
| Evan Cheng | df8c7fa | 2008-08-08 17:56:50 +0000 | [diff] [blame] | 41 | ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const { | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 42 | SectionKind::Kind Kind = SectionKindForGlobal(GV); | 
|  | 43 |  | 
|  | 44 | if (const Function *F = dyn_cast<Function>(GV)) { | 
|  | 45 | switch (F->getLinkage()) { | 
|  | 46 | default: assert(0 && "Unknown linkage type!"); | 
| Rafael Espindola | 6de96a1 | 2009-01-15 20:18:42 +0000 | [diff] [blame] | 47 | case Function::PrivateLinkage: | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 48 | case Function::InternalLinkage: | 
|  | 49 | case Function::DLLExportLinkage: | 
|  | 50 | case Function::ExternalLinkage: | 
| Anton Korobeynikov | 1f365bb | 2008-09-24 22:16:33 +0000 | [diff] [blame] | 51 | return TextSection; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 52 | case Function::WeakLinkage: | 
|  | 53 | case Function::LinkOnceLinkage: | 
|  | 54 | std::string Name = UniqueSectionForGlobal(GV, Kind); | 
|  | 55 | unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str()); | 
|  | 56 | return getNamedSection(Name.c_str(), Flags); | 
|  | 57 | } | 
|  | 58 | } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) { | 
| Duncan Sands | 08d9117 | 2008-09-29 11:25:42 +0000 | [diff] [blame] | 59 | if (GVar->mayBeOverridden()) { | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 60 | std::string Name = UniqueSectionForGlobal(GVar, Kind); | 
|  | 61 | unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str()); | 
|  | 62 | return getNamedSection(Name.c_str(), Flags); | 
|  | 63 | } else { | 
|  | 64 | switch (Kind) { | 
|  | 65 | case SectionKind::Data: | 
| Anton Korobeynikov | 4a4484e | 2008-07-22 17:09:41 +0000 | [diff] [blame] | 66 | case SectionKind::SmallData: | 
| Anton Korobeynikov | 1f365bb | 2008-09-24 22:16:33 +0000 | [diff] [blame] | 67 | return DataSection; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 68 | case SectionKind::BSS: | 
| Anton Korobeynikov | 4a4484e | 2008-07-22 17:09:41 +0000 | [diff] [blame] | 69 | case SectionKind::SmallBSS: | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 70 | // ELF targets usually have BSS sections | 
|  | 71 | return getBSSSection_(); | 
|  | 72 | case SectionKind::ROData: | 
| Anton Korobeynikov | 4a4484e | 2008-07-22 17:09:41 +0000 | [diff] [blame] | 73 | case SectionKind::SmallROData: | 
| Anton Korobeynikov | 8e7b939 | 2008-09-24 22:20:27 +0000 | [diff] [blame] | 74 | return getReadOnlySection(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 75 | case SectionKind::RODataMergeStr: | 
|  | 76 | return MergeableStringSection(GVar); | 
|  | 77 | case SectionKind::RODataMergeConst: | 
|  | 78 | return MergeableConstSection(GVar); | 
|  | 79 | case SectionKind::ThreadData: | 
|  | 80 | // ELF targets usually support TLS stuff | 
| Anton Korobeynikov | 22db305 | 2008-09-24 22:17:06 +0000 | [diff] [blame] | 81 | return TLSDataSection; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 82 | case SectionKind::ThreadBSS: | 
| Anton Korobeynikov | 22db305 | 2008-09-24 22:17:06 +0000 | [diff] [blame] | 83 | return TLSBSSSection; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 84 | default: | 
|  | 85 | assert(0 && "Unsuported section kind for global"); | 
|  | 86 | } | 
|  | 87 | } | 
|  | 88 | } else | 
|  | 89 | assert(0 && "Unsupported global"); | 
| Devang Patel | 56a8bb6 | 2009-01-05 17:31:22 +0000 | [diff] [blame] | 90 |  | 
|  | 91 | return NULL; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 92 | } | 
|  | 93 |  | 
|  | 94 | const Section* | 
| Anton Korobeynikov | ef643a4 | 2008-08-07 09:50:34 +0000 | [diff] [blame] | 95 | ELFTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const { | 
|  | 96 | // FIXME: Support data.rel stuff someday | 
|  | 97 | return MergeableConstSection(Ty); | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | const Section* | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 101 | ELFTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const { | 
| Anton Korobeynikov | 41573b2 | 2008-09-24 22:17:27 +0000 | [diff] [blame] | 102 | Constant *C = GV->getInitializer(); | 
| Anton Korobeynikov | 6c7b43c | 2008-08-07 09:51:02 +0000 | [diff] [blame] | 103 | return MergeableConstSection(C->getType()); | 
| Anton Korobeynikov | ef643a4 | 2008-08-07 09:50:34 +0000 | [diff] [blame] | 104 | } | 
|  | 105 |  | 
|  | 106 | inline const Section* | 
|  | 107 | ELFTargetAsmInfo::MergeableConstSection(const Type *Ty) const { | 
| Dan Gohman | ac41d9f | 2008-11-03 18:22:42 +0000 | [diff] [blame] | 108 | const TargetData *TD = TM.getTargetData(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 109 |  | 
|  | 110 | // FIXME: string here is temporary, until stuff will fully land in. | 
|  | 111 | // We cannot use {Four,Eight,Sixteen}ByteConstantSection here, since it's | 
|  | 112 | // currently directly used by asmprinter. | 
| Duncan Sands | dc020f9 | 2009-01-12 20:38:59 +0000 | [diff] [blame] | 113 | unsigned Size = TD->getTypePaddedSize(Ty); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 114 | if (Size == 4 || Size == 8 || Size == 16) { | 
|  | 115 | std::string Name =  ".rodata.cst" + utostr(Size); | 
|  | 116 |  | 
|  | 117 | return getNamedSection(Name.c_str(), | 
|  | 118 | SectionFlags::setEntitySize(SectionFlags::Mergeable, | 
|  | 119 | Size)); | 
|  | 120 | } | 
|  | 121 |  | 
| Anton Korobeynikov | 8e7b939 | 2008-09-24 22:20:27 +0000 | [diff] [blame] | 122 | return getReadOnlySection(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
|  | 125 | const Section* | 
|  | 126 | ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const { | 
| Dan Gohman | ac41d9f | 2008-11-03 18:22:42 +0000 | [diff] [blame] | 127 | const TargetData *TD = TM.getTargetData(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 128 | Constant *C = cast<GlobalVariable>(GV)->getInitializer(); | 
| Anton Korobeynikov | 70d4c08 | 2009-01-27 22:29:24 +0000 | [diff] [blame] | 129 | const Type *Ty = cast<ArrayType>(C->getType())->getElementType(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 130 |  | 
| Duncan Sands | dc020f9 | 2009-01-12 20:38:59 +0000 | [diff] [blame] | 131 | unsigned Size = TD->getTypePaddedSize(Ty); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 132 | if (Size <= 16) { | 
| Anton Korobeynikov | 1c2de10 | 2008-08-07 09:54:40 +0000 | [diff] [blame] | 133 | assert(getCStringSection() && "Should have string section prefix"); | 
|  | 134 |  | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 135 | // We also need alignment here | 
| Anton Korobeynikov | e61ad2b | 2008-07-21 18:29:23 +0000 | [diff] [blame] | 136 | unsigned Align = TD->getPrefTypeAlignment(Ty); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 137 | if (Align < Size) | 
|  | 138 | Align = Size; | 
|  | 139 |  | 
|  | 140 | std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align); | 
|  | 141 | unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable | | 
|  | 142 | SectionFlags::Strings, | 
|  | 143 | Size); | 
|  | 144 | return getNamedSection(Name.c_str(), Flags); | 
|  | 145 | } | 
|  | 146 |  | 
| Anton Korobeynikov | 8e7b939 | 2008-09-24 22:20:27 +0000 | [diff] [blame] | 147 | return getReadOnlySection(); | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 148 | } | 
|  | 149 |  | 
| Anton Korobeynikov | 44b4a9a | 2008-08-16 12:57:07 +0000 | [diff] [blame] | 150 | std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const { | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 151 | std::string Flags = ",\""; | 
|  | 152 |  | 
|  | 153 | if (!(flags & SectionFlags::Debug)) | 
|  | 154 | Flags += 'a'; | 
|  | 155 | if (flags & SectionFlags::Code) | 
|  | 156 | Flags += 'x'; | 
|  | 157 | if (flags & SectionFlags::Writeable) | 
|  | 158 | Flags += 'w'; | 
|  | 159 | if (flags & SectionFlags::Mergeable) | 
|  | 160 | Flags += 'M'; | 
|  | 161 | if (flags & SectionFlags::Strings) | 
|  | 162 | Flags += 'S'; | 
|  | 163 | if (flags & SectionFlags::TLS) | 
|  | 164 | Flags += 'T'; | 
| Anton Korobeynikov | 4a4484e | 2008-07-22 17:09:41 +0000 | [diff] [blame] | 165 | if (flags & SectionFlags::Small) | 
|  | 166 | Flags += 's'; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 167 |  | 
| Anton Korobeynikov | 9dbbd75 | 2008-08-07 09:55:06 +0000 | [diff] [blame] | 168 | Flags += "\","; | 
|  | 169 |  | 
|  | 170 | // If comment string is '@', e.g. as on ARM - use '%' instead | 
|  | 171 | if (strcmp(CommentString, "@") == 0) | 
|  | 172 | Flags += '%'; | 
|  | 173 | else | 
|  | 174 | Flags += '@'; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 175 |  | 
|  | 176 | // FIXME: There can be exceptions here | 
|  | 177 | if (flags & SectionFlags::BSS) | 
| Anton Korobeynikov | 9dbbd75 | 2008-08-07 09:55:06 +0000 | [diff] [blame] | 178 | Flags += "nobits"; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 179 | else | 
| Anton Korobeynikov | 9dbbd75 | 2008-08-07 09:55:06 +0000 | [diff] [blame] | 180 | Flags += "progbits"; | 
| Anton Korobeynikov | 1d03fcc | 2008-07-19 13:14:11 +0000 | [diff] [blame] | 181 |  | 
|  | 182 | if (unsigned entitySize = SectionFlags::getEntitySize(flags)) | 
|  | 183 | Flags += "," + utostr(entitySize); | 
|  | 184 |  | 
|  | 185 | return Flags; | 
|  | 186 | } |