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" 26using namespace llvm; 27 28typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; 29typedef StringMap<const MCSectionELF*> ELFUniqueMapTy; 30typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; 31 32 33MCContext::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 53MCContext::~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 70MCSymbol *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 86MCSymbol *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 111MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { 112 SmallString<128> NameSV; 113 Name.toVector(NameSV); 114 return GetOrCreateSymbol(NameSV.str()); 115} 116 117MCSymbol *MCContext::CreateTempSymbol() { 118 SmallString<128> NameSV; 119 raw_svector_ostream(NameSV) 120 << MAI.getPrivateGlobalPrefix() << "tmp" << NextUniqueID++; 121 return CreateSymbol(NameSV); 122} 123 124unsigned 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 131unsigned 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 138MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { 139 return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + 140 Twine(LocalLabelVal) + 141 "\2" + 142 Twine(NextInstance(LocalLabelVal))); 143} 144MCSymbol *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 152MCSymbol *MCContext::LookupSymbol(StringRef Name) const { 153 return Symbols.lookup(Name); 154} 155 156MCSymbol *MCContext::LookupSymbol(const Twine &Name) const { 157 SmallString<128> NameSV; 158 Name.toVector(NameSV); 159 return LookupSymbol(NameSV.str()); 160} 161 162//===----------------------------------------------------------------------===// 163// Section Management 164//===----------------------------------------------------------------------===// 165 166const MCSectionMachO *MCContext:: 167getMachOSection(StringRef Segment, StringRef Section, 168 unsigned TypeAndAttributes, 169 unsigned Reserved2, SectionKind Kind) { 170 171 // We unique sections by their segment/section pair. The returned section 172 // may not have the same flags as the requested section, if so this should be 173 // diagnosed by the client as an error. 174 175 // Create the map if it doesn't already exist. 176 if (MachOUniquingMap == 0) 177 MachOUniquingMap = new MachOUniqueMapTy(); 178 MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap; 179 180 // Form the name to look up. 181 SmallString<64> Name; 182 Name += Segment; 183 Name.push_back(','); 184 Name += Section; 185 186 // Do the lookup, if we have a hit, return it. 187 const MCSectionMachO *&Entry = Map[Name.str()]; 188 if (Entry) return Entry; 189 190 // Otherwise, return a new section. 191 return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes, 192 Reserved2, Kind); 193} 194 195const MCSectionELF *MCContext:: 196getELFSection(StringRef Section, unsigned Type, unsigned Flags, 197 SectionKind Kind) { 198 return getELFSection(Section, Type, Flags, Kind, 0, ""); 199} 200 201const MCSectionELF *MCContext:: 202getELFSection(StringRef Section, unsigned Type, unsigned Flags, 203 SectionKind Kind, unsigned EntrySize, StringRef Group) { 204 if (ELFUniquingMap == 0) 205 ELFUniquingMap = new ELFUniqueMapTy(); 206 ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap; 207 208 // Do the lookup, if we have a hit, return it. 209 StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section); 210 if (Entry.getValue()) return Entry.getValue(); 211 212 // Possibly refine the entry size first. 213 if (!EntrySize) { 214 EntrySize = MCSectionELF::DetermineEntrySize(Kind); 215 } 216 217 MCSymbol *GroupSym = NULL; 218 if (!Group.empty()) 219 GroupSym = GetOrCreateSymbol(Group); 220 221 MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags, 222 Kind, EntrySize, GroupSym); 223 Entry.setValue(Result); 224 return Result; 225} 226 227const MCSectionELF *MCContext::CreateELFGroupSection() { 228 MCSectionELF *Result = 229 new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0, 230 SectionKind::getReadOnly(), 4, NULL); 231 return Result; 232} 233 234const MCSection *MCContext::getCOFFSection(StringRef Section, 235 unsigned Characteristics, 236 int Selection, 237 SectionKind Kind) { 238 if (COFFUniquingMap == 0) 239 COFFUniquingMap = new COFFUniqueMapTy(); 240 COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; 241 242 // Do the lookup, if we have a hit, return it. 243 StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section); 244 if (Entry.getValue()) return Entry.getValue(); 245 246 MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), 247 Characteristics, 248 Selection, Kind); 249 250 Entry.setValue(Result); 251 return Result; 252} 253 254//===----------------------------------------------------------------------===// 255// Dwarf Management 256//===----------------------------------------------------------------------===// 257 258/// GetDwarfFile - takes a file name an number to place in the dwarf file and 259/// directory tables. If the file number has already been allocated it is an 260/// error and zero is returned and the client reports the error, else the 261/// allocated file number is returned. The file numbers may be in any order. 262unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName, 263 unsigned FileNumber) { 264 // TODO: a FileNumber of zero says to use the next available file number. 265 // Note: in GenericAsmParser::ParseDirectiveFile() FileNumber was checked 266 // to not be less than one. This needs to be change to be not less than zero. 267 268 // Make space for this FileNumber in the MCDwarfFiles vector if needed. 269 if (FileNumber >= MCDwarfFiles.size()) { 270 MCDwarfFiles.resize(FileNumber + 1); 271 } else { 272 MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber]; 273 if (ExistingFile) 274 // It is an error to use see the same number more than once. 275 return 0; 276 } 277 278 // Get the new MCDwarfFile slot for this FileNumber. 279 MCDwarfFile *&File = MCDwarfFiles[FileNumber]; 280 281 if (Directory.empty()) { 282 // Separate the directory part from the basename of the FileName. 283 StringRef tFileName = sys::path::filename(FileName); 284 if (!tFileName.empty()) { 285 Directory = sys::path::parent_path(FileName); 286 if (!Directory.empty()) 287 FileName = tFileName; 288 } 289 } 290 291 // Find or make a entry in the MCDwarfDirs vector for this Directory. 292 // Capture directory name. 293 unsigned DirIndex; 294 if (Directory.empty()) { 295 // For FileNames with no directories a DirIndex of 0 is used. 296 DirIndex = 0; 297 } else { 298 DirIndex = 0; 299 for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { 300 if (Directory == MCDwarfDirs[DirIndex]) 301 break; 302 } 303 if (DirIndex >= MCDwarfDirs.size()) { 304 char *Buf = static_cast<char *>(Allocate(Directory.size())); 305 memcpy(Buf, Directory.data(), Directory.size()); 306 MCDwarfDirs.push_back(StringRef(Buf, Directory.size())); 307 } 308 // The DirIndex is one based, as DirIndex of 0 is used for FileNames with 309 // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the 310 // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames 311 // are stored at MCDwarfFiles[FileNumber].Name . 312 DirIndex++; 313 } 314 315 // Now make the MCDwarfFile entry and place it in the slot in the MCDwarfFiles 316 // vector. 317 char *Buf = static_cast<char *>(Allocate(FileName.size())); 318 memcpy(Buf, FileName.data(), FileName.size()); 319 File = new (*this) MCDwarfFile(StringRef(Buf, FileName.size()), DirIndex); 320 321 // return the allocated FileNumber. 322 return FileNumber; 323} 324 325/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it 326/// currently is assigned and false otherwise. 327bool MCContext::isValidDwarfFileNumber(unsigned FileNumber) { 328 if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size()) 329 return false; 330 331 return MCDwarfFiles[FileNumber] != 0; 332} 333 334void MCContext::FatalError(SMLoc Loc, const Twine &Msg) { 335 // If we have a source manager and a location, use it. Otherwise just 336 // use the generic report_fatal_error(). 337 if (!SrcMgr || Loc == SMLoc()) 338 report_fatal_error(Msg); 339 340 // Use the source manager to print the message. 341 SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); 342 343 // If we reached here, we are failing ungracefully. Run the interrupt handlers 344 // to make sure any special cleanups get done, in particular that we remove 345 // files registered with RemoveFileOnSignal. 346 sys::RunInterruptHandlers(); 347 exit(1); 348} 349