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/ADT/SmallString.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCDwarf.h"
15#include "llvm/MC/MCLabel.h"
16#include "llvm/MC/MCObjectFileInfo.h"
17#include "llvm/MC/MCRegisterInfo.h"
18#include "llvm/MC/MCSectionCOFF.h"
19#include "llvm/MC/MCSectionELF.h"
20#include "llvm/MC/MCSectionMachO.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/Support/ELF.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/MemoryBuffer.h"
26#include "llvm/Support/Signals.h"
27#include "llvm/Support/SourceMgr.h"
28#include <map>
29
30using namespace llvm;
31
32MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
33                     const MCObjectFileInfo *mofi, const SourceMgr *mgr,
34                     bool DoAutoReset)
35    : SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), Allocator(),
36      Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0),
37      CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), DwarfLocSeen(false),
38      GenDwarfForAssembly(false), GenDwarfFileNumber(0), DwarfVersion(4),
39      AllowTemporaryLabels(true), DwarfCompileUnitID(0),
40      AutoReset(DoAutoReset) {
41
42  std::error_code EC = llvm::sys::fs::current_path(CompilationDir);
43  if (EC)
44    CompilationDir.clear();
45
46  SecureLogFile = getenv("AS_SECURE_LOG_FILE");
47  SecureLog = nullptr;
48  SecureLogUsed = false;
49
50  if (SrcMgr && SrcMgr->getNumBuffers())
51    MainFileName =
52        SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier();
53}
54
55MCContext::~MCContext() {
56
57  if (AutoReset)
58    reset();
59
60  // NOTE: The symbols are all allocated out of a bump pointer allocator,
61  // we don't need to free them here.
62
63  // If the stream for the .secure_log_unique directive was created free it.
64  delete (raw_ostream*)SecureLog;
65}
66
67//===----------------------------------------------------------------------===//
68// Module Lifetime Management
69//===----------------------------------------------------------------------===//
70
71void MCContext::reset() {
72  UsedNames.clear();
73  Symbols.clear();
74  Allocator.Reset();
75  Instances.clear();
76  MCDwarfLineTablesCUMap.clear();
77  MCGenDwarfLabelEntries.clear();
78  DwarfDebugFlags = StringRef();
79  DwarfCompileUnitID = 0;
80  CurrentDwarfLoc = MCDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0);
81
82  MachOUniquingMap.clear();
83  ELFUniquingMap.clear();
84  COFFUniquingMap.clear();
85
86  NextUniqueID = 0;
87  AllowTemporaryLabels = true;
88  DwarfLocSeen = false;
89  GenDwarfForAssembly = false;
90  GenDwarfFileNumber = 0;
91}
92
93//===----------------------------------------------------------------------===//
94// Symbol Manipulation
95//===----------------------------------------------------------------------===//
96
97MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) {
98  assert(!Name.empty() && "Normal symbols cannot be unnamed!");
99
100  // Do the lookup and get the entire StringMapEntry.  We want access to the
101  // key if we are creating the entry.
102  StringMapEntry<MCSymbol*> &Entry = Symbols.GetOrCreateValue(Name);
103  MCSymbol *Sym = Entry.getValue();
104
105  if (Sym)
106    return Sym;
107
108  Sym = CreateSymbol(Name);
109  Entry.setValue(Sym);
110  return Sym;
111}
112
113MCSymbol *MCContext::CreateSymbol(StringRef Name) {
114  // Determine whether this is an assembler temporary or normal label, if used.
115  bool isTemporary = false;
116  if (AllowTemporaryLabels)
117    isTemporary = Name.startswith(MAI->getPrivateGlobalPrefix());
118
119  StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name);
120  if (NameEntry->getValue()) {
121    assert(isTemporary && "Cannot rename non-temporary symbols");
122    SmallString<128> NewName = Name;
123    do {
124      NewName.resize(Name.size());
125      raw_svector_ostream(NewName) << NextUniqueID++;
126      NameEntry = &UsedNames.GetOrCreateValue(NewName);
127    } while (NameEntry->getValue());
128  }
129  NameEntry->setValue(true);
130
131  // Ok, the entry doesn't already exist.  Have the MCSymbol object itself refer
132  // to the copy of the string that is embedded in the UsedNames entry.
133  MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary);
134
135  return Result;
136}
137
138MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
139  SmallString<128> NameSV;
140  return GetOrCreateSymbol(Name.toStringRef(NameSV));
141}
142
143MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() {
144  SmallString<128> NameSV;
145  raw_svector_ostream(NameSV)
146    << MAI->getLinkerPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
147  return CreateSymbol(NameSV);
148}
149
150MCSymbol *MCContext::CreateTempSymbol() {
151  SmallString<128> NameSV;
152  raw_svector_ostream(NameSV)
153    << MAI->getPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
154  return CreateSymbol(NameSV);
155}
156
157unsigned MCContext::NextInstance(unsigned LocalLabelVal) {
158  MCLabel *&Label = Instances[LocalLabelVal];
159  if (!Label)
160    Label = new (*this) MCLabel(0);
161  return Label->incInstance();
162}
163
164unsigned MCContext::GetInstance(unsigned LocalLabelVal) {
165  MCLabel *&Label = Instances[LocalLabelVal];
166  if (!Label)
167    Label = new (*this) MCLabel(0);
168  return Label->getInstance();
169}
170
171MCSymbol *MCContext::getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal,
172                                                       unsigned Instance) {
173  MCSymbol *&Sym = LocalSymbols[std::make_pair(LocalLabelVal, Instance)];
174  if (!Sym)
175    Sym = CreateTempSymbol();
176  return Sym;
177}
178
179MCSymbol *MCContext::CreateDirectionalLocalSymbol(unsigned LocalLabelVal) {
180  unsigned Instance = NextInstance(LocalLabelVal);
181  return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance);
182}
183
184MCSymbol *MCContext::GetDirectionalLocalSymbol(unsigned LocalLabelVal,
185                                               bool Before) {
186  unsigned Instance = GetInstance(LocalLabelVal);
187  if (!Before)
188    ++Instance;
189  return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance);
190}
191
192MCSymbol *MCContext::LookupSymbol(StringRef Name) const {
193  return Symbols.lookup(Name);
194}
195
196MCSymbol *MCContext::LookupSymbol(const Twine &Name) const {
197  SmallString<128> NameSV;
198  Name.toVector(NameSV);
199  return LookupSymbol(NameSV.str());
200}
201
202//===----------------------------------------------------------------------===//
203// Section Management
204//===----------------------------------------------------------------------===//
205
206const MCSectionMachO *MCContext::
207getMachOSection(StringRef Segment, StringRef Section,
208                unsigned TypeAndAttributes,
209                unsigned Reserved2, SectionKind Kind) {
210
211  // We unique sections by their segment/section pair.  The returned section
212  // may not have the same flags as the requested section, if so this should be
213  // diagnosed by the client as an error.
214
215  // Form the name to look up.
216  SmallString<64> Name;
217  Name += Segment;
218  Name.push_back(',');
219  Name += Section;
220
221  // Do the lookup, if we have a hit, return it.
222  const MCSectionMachO *&Entry = MachOUniquingMap[Name.str()];
223  if (Entry) return Entry;
224
225  // Otherwise, return a new section.
226  return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes,
227                                            Reserved2, Kind);
228}
229
230const MCSectionELF *MCContext::
231getELFSection(StringRef Section, unsigned Type, unsigned Flags,
232              SectionKind Kind) {
233  return getELFSection(Section, Type, Flags, Kind, 0, "");
234}
235
236void MCContext::renameELFSection(const MCSectionELF *Section, StringRef Name) {
237  StringRef GroupName;
238  if (const MCSymbol *Group = Section->getGroup())
239    GroupName = Group->getName();
240
241  ELFUniquingMap.erase(SectionGroupPair(Section->getSectionName(), GroupName));
242  auto I =
243      ELFUniquingMap.insert(std::make_pair(SectionGroupPair(Name, GroupName),
244                                           Section)).first;
245  StringRef CachedName = I->first.first;
246  const_cast<MCSectionELF*>(Section)->setSectionName(CachedName);
247}
248
249const MCSectionELF *MCContext::
250getELFSection(StringRef Section, unsigned Type, unsigned Flags,
251              SectionKind Kind, unsigned EntrySize, StringRef Group) {
252  // Do the lookup, if we have a hit, return it.
253  auto IterBool = ELFUniquingMap.insert(
254      std::make_pair(SectionGroupPair(Section, Group), nullptr));
255  auto &Entry = *IterBool.first;
256  if (!IterBool.second) return Entry.second;
257
258  // Possibly refine the entry size first.
259  if (!EntrySize) {
260    EntrySize = MCSectionELF::DetermineEntrySize(Kind);
261  }
262
263  MCSymbol *GroupSym = nullptr;
264  if (!Group.empty())
265    GroupSym = GetOrCreateSymbol(Group);
266
267  StringRef CachedName = Entry.first.first;
268  MCSectionELF *Result = new (*this)
269      MCSectionELF(CachedName, Type, Flags, Kind, EntrySize, GroupSym);
270  Entry.second = Result;
271  return Result;
272}
273
274const MCSectionELF *MCContext::CreateELFGroupSection() {
275  MCSectionELF *Result =
276    new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0,
277                             SectionKind::getReadOnly(), 4, nullptr);
278  return Result;
279}
280
281const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
282                                               unsigned Characteristics,
283                                               SectionKind Kind,
284                                               StringRef COMDATSymName,
285                                               int Selection) {
286  // Do the lookup, if we have a hit, return it.
287
288  SectionGroupTriple T(Section, COMDATSymName, Selection);
289  auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr));
290  auto Iter = IterBool.first;
291  if (!IterBool.second)
292    return Iter->second;
293
294  const MCSymbol *COMDATSymbol = nullptr;
295  if (!COMDATSymName.empty())
296    COMDATSymbol = GetOrCreateSymbol(COMDATSymName);
297
298  StringRef CachedName = std::get<0>(Iter->first);
299  MCSectionCOFF *Result = new (*this)
300      MCSectionCOFF(CachedName, Characteristics, COMDATSymbol, Selection, Kind);
301
302  Iter->second = Result;
303  return Result;
304}
305
306const MCSectionCOFF *
307MCContext::getCOFFSection(StringRef Section, unsigned Characteristics,
308                          SectionKind Kind) {
309  return getCOFFSection(Section, Characteristics, Kind, "", 0);
310}
311
312const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) {
313  SectionGroupTriple T(Section, "", 0);
314  auto Iter = COFFUniquingMap.find(T);
315  if (Iter == COFFUniquingMap.end())
316    return nullptr;
317  return Iter->second;
318}
319
320//===----------------------------------------------------------------------===//
321// Dwarf Management
322//===----------------------------------------------------------------------===//
323
324/// GetDwarfFile - takes a file name an number to place in the dwarf file and
325/// directory tables.  If the file number has already been allocated it is an
326/// error and zero is returned and the client reports the error, else the
327/// allocated file number is returned.  The file numbers may be in any order.
328unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName,
329                                 unsigned FileNumber, unsigned CUID) {
330  MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
331  return Table.getFile(Directory, FileName, FileNumber);
332}
333
334/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
335/// currently is assigned and false otherwise.
336bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
337  const SmallVectorImpl<MCDwarfFile>& MCDwarfFiles = getMCDwarfFiles(CUID);
338  if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
339    return false;
340
341  return !MCDwarfFiles[FileNumber].Name.empty();
342}
343
344/// finalizeDwarfSections - Emit end symbols for each non-empty code section.
345/// Also remove empty sections from SectionStartEndSyms, to avoid generating
346/// useless debug info for them.
347void MCContext::finalizeDwarfSections(MCStreamer &MCOS) {
348  MCContext &context = MCOS.getContext();
349
350  auto sec = SectionStartEndSyms.begin();
351  while (sec != SectionStartEndSyms.end()) {
352    assert(sec->second.first && "Start symbol must be set by now");
353    MCOS.SwitchSection(sec->first);
354    if (MCOS.mayHaveInstructions()) {
355      MCSymbol *SectionEndSym = context.CreateTempSymbol();
356      MCOS.EmitLabel(SectionEndSym);
357      sec->second.second = SectionEndSym;
358      ++sec;
359    } else {
360      MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >::iterator
361        to_erase = sec;
362      sec = SectionStartEndSyms.erase(to_erase);
363    }
364  }
365}
366
367void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const {
368  // If we have a source manager and a location, use it. Otherwise just
369  // use the generic report_fatal_error().
370  if (!SrcMgr || Loc == SMLoc())
371    report_fatal_error(Msg, false);
372
373  // Use the source manager to print the message.
374  SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg);
375
376  // If we reached here, we are failing ungracefully. Run the interrupt handlers
377  // to make sure any special cleanups get done, in particular that we remove
378  // files registered with RemoveFileOnSignal.
379  sys::RunInterruptHandlers();
380  exit(1);
381}
382