1 //===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===// 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 #include "llvm/MC/MCContext.h" 11 #include "llvm/MC/MCAsmInfo.h" 12 #include "llvm/MC/MCObjectFileInfo.h" 13 #include "llvm/MC/MCRegisterInfo.h" 14 #include "llvm/MC/MCSectionMachO.h" 15 #include "llvm/MC/MCSectionELF.h" 16 #include "llvm/MC/MCSectionCOFF.h" 17 #include "llvm/MC/MCSymbol.h" 18 #include "llvm/MC/MCLabel.h" 19 #include "llvm/MC/MCDwarf.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/ADT/Twine.h" 22 #include "llvm/Support/ELF.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/SourceMgr.h" 25 #include "llvm/Support/Signals.h" 26 using namespace llvm; 27 28 typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; 29 typedef StringMap<const MCSectionELF*> ELFUniqueMapTy; 30 typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; 31 32 33 MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri, 34 const MCObjectFileInfo *mofi, const SourceMgr *mgr) : 35 SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), 36 Allocator(), Symbols(Allocator), UsedNames(Allocator), 37 NextUniqueID(0), 38 CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), 39 AllowTemporaryLabels(true) { 40 MachOUniquingMap = 0; 41 ELFUniquingMap = 0; 42 COFFUniquingMap = 0; 43 44 SecureLogFile = getenv("AS_SECURE_LOG_FILE"); 45 SecureLog = 0; 46 SecureLogUsed = false; 47 48 DwarfLocSeen = false; 49 GenDwarfForAssembly = false; 50 GenDwarfFileNumber = 0; 51 } 52 53 MCContext::~MCContext() { 54 // NOTE: The symbols are all allocated out of a bump pointer allocator, 55 // we don't need to free them here. 56 57 // If we have the MachO uniquing map, free it. 58 delete (MachOUniqueMapTy*)MachOUniquingMap; 59 delete (ELFUniqueMapTy*)ELFUniquingMap; 60 delete (COFFUniqueMapTy*)COFFUniquingMap; 61 62 // If the stream for the .secure_log_unique directive was created free it. 63 delete (raw_ostream*)SecureLog; 64 } 65 66 //===----------------------------------------------------------------------===// 67 // Symbol Manipulation 68 //===----------------------------------------------------------------------===// 69 70 MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { 71 assert(!Name.empty() && "Normal symbols cannot be unnamed!"); 72 73 // Do the lookup and get the entire StringMapEntry. We want access to the 74 // key if we are creating the entry. 75 StringMapEntry<MCSymbol*> &Entry = Symbols.GetOrCreateValue(Name); 76 MCSymbol *Sym = Entry.getValue(); 77 78 if (Sym) 79 return Sym; 80 81 Sym = CreateSymbol(Name); 82 Entry.setValue(Sym); 83 return Sym; 84 } 85 86 MCSymbol *MCContext::CreateSymbol(StringRef Name) { 87 // Determine whether this is an assembler temporary or normal label, if used. 88 bool isTemporary = false; 89 if (AllowTemporaryLabels) 90 isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix()); 91 92 StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name); 93 if (NameEntry->getValue()) { 94 assert(isTemporary && "Cannot rename non temporary symbols"); 95 SmallString<128> NewName = Name; 96 do { 97 NewName.resize(Name.size()); 98 raw_svector_ostream(NewName) << NextUniqueID++; 99 NameEntry = &UsedNames.GetOrCreateValue(NewName); 100 } while (NameEntry->getValue()); 101 } 102 NameEntry->setValue(true); 103 104 // Ok, the entry doesn't already exist. Have the MCSymbol object itself refer 105 // to the copy of the string that is embedded in the UsedNames entry. 106 MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary); 107 108 return Result; 109 } 110 111 MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { 112 SmallString<128> NameSV; 113 Name.toVector(NameSV); 114 return GetOrCreateSymbol(NameSV.str()); 115 } 116 117 MCSymbol *MCContext::CreateTempSymbol() { 118 SmallString<128> NameSV; 119 raw_svector_ostream(NameSV) 120 << MAI.getPrivateGlobalPrefix() << "tmp" << NextUniqueID++; 121 return CreateSymbol(NameSV); 122 } 123 124 unsigned MCContext::NextInstance(int64_t LocalLabelVal) { 125 MCLabel *&Label = Instances[LocalLabelVal]; 126 if (!Label) 127 Label = new (*this) MCLabel(0); 128 return Label->incInstance(); 129 } 130 131 unsigned MCContext::GetInstance(int64_t LocalLabelVal) { 132 MCLabel *&Label = Instances[LocalLabelVal]; 133 if (!Label) 134 Label = new (*this) MCLabel(0); 135 return Label->getInstance(); 136 } 137 138 MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { 139 return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + 140 Twine(LocalLabelVal) + 141 "\2" + 142 Twine(NextInstance(LocalLabelVal))); 143 } 144 MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal, 145 int bORf) { 146 return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + 147 Twine(LocalLabelVal) + 148 "\2" + 149 Twine(GetInstance(LocalLabelVal) + bORf)); 150 } 151 152 MCSymbol *MCContext::LookupSymbol(StringRef Name) const { 153 return Symbols.lookup(Name); 154 } 155 156 //===----------------------------------------------------------------------===// 157 // Section Management 158 //===----------------------------------------------------------------------===// 159 160 const MCSectionMachO *MCContext:: 161 getMachOSection(StringRef Segment, StringRef Section, 162 unsigned TypeAndAttributes, 163 unsigned Reserved2, SectionKind Kind) { 164 165 // We unique sections by their segment/section pair. The returned section 166 // may not have the same flags as the requested section, if so this should be 167 // diagnosed by the client as an error. 168 169 // Create the map if it doesn't already exist. 170 if (MachOUniquingMap == 0) 171 MachOUniquingMap = new MachOUniqueMapTy(); 172 MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap; 173 174 // Form the name to look up. 175 SmallString<64> Name; 176 Name += Segment; 177 Name.push_back(','); 178 Name += Section; 179 180 // Do the lookup, if we have a hit, return it. 181 const MCSectionMachO *&Entry = Map[Name.str()]; 182 if (Entry) return Entry; 183 184 // Otherwise, return a new section. 185 return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes, 186 Reserved2, Kind); 187 } 188 189 const MCSectionELF *MCContext:: 190 getELFSection(StringRef Section, unsigned Type, unsigned Flags, 191 SectionKind Kind) { 192 return getELFSection(Section, Type, Flags, Kind, 0, ""); 193 } 194 195 const MCSectionELF *MCContext:: 196 getELFSection(StringRef Section, unsigned Type, unsigned Flags, 197 SectionKind Kind, unsigned EntrySize, StringRef Group) { 198 if (ELFUniquingMap == 0) 199 ELFUniquingMap = new ELFUniqueMapTy(); 200 ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap; 201 202 // Do the lookup, if we have a hit, return it. 203 StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section); 204 if (Entry.getValue()) return Entry.getValue(); 205 206 // Possibly refine the entry size first. 207 if (!EntrySize) { 208 EntrySize = MCSectionELF::DetermineEntrySize(Kind); 209 } 210 211 MCSymbol *GroupSym = NULL; 212 if (!Group.empty()) 213 GroupSym = GetOrCreateSymbol(Group); 214 215 MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags, 216 Kind, EntrySize, GroupSym); 217 Entry.setValue(Result); 218 return Result; 219 } 220 221 const MCSectionELF *MCContext::CreateELFGroupSection() { 222 MCSectionELF *Result = 223 new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0, 224 SectionKind::getReadOnly(), 4, NULL); 225 return Result; 226 } 227 228 const MCSection *MCContext::getCOFFSection(StringRef Section, 229 unsigned Characteristics, 230 int Selection, 231 SectionKind Kind) { 232 if (COFFUniquingMap == 0) 233 COFFUniquingMap = new COFFUniqueMapTy(); 234 COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; 235 236 // Do the lookup, if we have a hit, return it. 237 StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section); 238 if (Entry.getValue()) return Entry.getValue(); 239 240 MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), 241 Characteristics, 242 Selection, Kind); 243 244 Entry.setValue(Result); 245 return Result; 246 } 247 248 //===----------------------------------------------------------------------===// 249 // Dwarf Management 250 //===----------------------------------------------------------------------===// 251 252 /// GetDwarfFile - takes a file name an number to place in the dwarf file and 253 /// directory tables. If the file number has already been allocated it is an 254 /// error and zero is returned and the client reports the error, else the 255 /// allocated file number is returned. The file numbers may be in any order. 256 unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName, 257 unsigned FileNumber) { 258 // TODO: a FileNumber of zero says to use the next available file number. 259 // Note: in GenericAsmParser::ParseDirectiveFile() FileNumber was checked 260 // to not be less than one. This needs to be change to be not less than zero. 261 262 // Make space for this FileNumber in the MCDwarfFiles vector if needed. 263 if (FileNumber >= MCDwarfFiles.size()) { 264 MCDwarfFiles.resize(FileNumber + 1); 265 } else { 266 MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber]; 267 if (ExistingFile) 268 // It is an error to use see the same number more than once. 269 return 0; 270 } 271 272 // Get the new MCDwarfFile slot for this FileNumber. 273 MCDwarfFile *&File = MCDwarfFiles[FileNumber]; 274 275 if (Directory.empty()) { 276 // Separate the directory part from the basename of the FileName. 277 std::pair<StringRef, StringRef> Slash = FileName.rsplit('/'); 278 Directory = Slash.second; 279 if (!Directory.empty()) { 280 Directory = Slash.first; 281 FileName = Slash.second; 282 } 283 } 284 285 // Find or make a entry in the MCDwarfDirs vector for this Directory. 286 // Capture directory name. 287 unsigned DirIndex; 288 if (Directory.empty()) { 289 // For FileNames with no directories a DirIndex of 0 is used. 290 DirIndex = 0; 291 } else { 292 DirIndex = 0; 293 for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { 294 if (Directory == MCDwarfDirs[DirIndex]) 295 break; 296 } 297 if (DirIndex >= MCDwarfDirs.size()) { 298 char *Buf = static_cast<char *>(Allocate(Directory.size())); 299 memcpy(Buf, Directory.data(), Directory.size()); 300 MCDwarfDirs.push_back(StringRef(Buf, Directory.size())); 301 } 302 // The DirIndex is one based, as DirIndex of 0 is used for FileNames with 303 // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the 304 // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames 305 // are stored at MCDwarfFiles[FileNumber].Name . 306 DirIndex++; 307 } 308 309 // Now make the MCDwarfFile entry and place it in the slot in the MCDwarfFiles 310 // vector. 311 char *Buf = static_cast<char *>(Allocate(FileName.size())); 312 memcpy(Buf, FileName.data(), FileName.size()); 313 File = new (*this) MCDwarfFile(StringRef(Buf, FileName.size()), DirIndex); 314 315 // return the allocated FileNumber. 316 return FileNumber; 317 } 318 319 /// isValidDwarfFileNumber - takes a dwarf file number and returns true if it 320 /// currently is assigned and false otherwise. 321 bool MCContext::isValidDwarfFileNumber(unsigned FileNumber) { 322 if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size()) 323 return false; 324 325 return MCDwarfFiles[FileNumber] != 0; 326 } 327 328 void MCContext::FatalError(SMLoc Loc, const Twine &Msg) { 329 // If we have a source manager and a location, use it. Otherwise just 330 // use the generic report_fatal_error(). 331 if (!SrcMgr || Loc == SMLoc()) 332 report_fatal_error(Msg); 333 334 // Use the source manager to print the message. 335 SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); 336 337 // If we reached here, we are failing ungracefully. Run the interrupt handlers 338 // to make sure any special cleanups get done, in particular that we remove 339 // files registered with RemoveFileOnSignal. 340 sys::RunInterruptHandlers(); 341 exit(1); 342 } 343