1249259Sdim//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim//  This file implements LLVMContext, as a wrapper around the opaque
11249259Sdim//  class LLVMContextImpl.
12249259Sdim//
13249259Sdim//===----------------------------------------------------------------------===//
14249259Sdim
15249259Sdim#include "llvm/IR/LLVMContext.h"
16249259Sdim#include "LLVMContextImpl.h"
17249259Sdim#include "llvm/IR/Constants.h"
18249259Sdim#include "llvm/IR/Instruction.h"
19249259Sdim#include "llvm/IR/Metadata.h"
20249259Sdim#include "llvm/Support/ManagedStatic.h"
21249259Sdim#include "llvm/Support/SourceMgr.h"
22249259Sdim#include <cctype>
23249259Sdimusing namespace llvm;
24249259Sdim
25249259Sdimstatic ManagedStatic<LLVMContext> GlobalContext;
26249259Sdim
27249259SdimLLVMContext& llvm::getGlobalContext() {
28249259Sdim  return *GlobalContext;
29249259Sdim}
30249259Sdim
31249259SdimLLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
32249259Sdim  // Create the fixed metadata kinds. This is done in the same order as the
33249259Sdim  // MD_* enum values so that they correspond.
34249259Sdim
35249259Sdim  // Create the 'dbg' metadata kind.
36249259Sdim  unsigned DbgID = getMDKindID("dbg");
37249259Sdim  assert(DbgID == MD_dbg && "dbg kind id drifted"); (void)DbgID;
38249259Sdim
39249259Sdim  // Create the 'tbaa' metadata kind.
40249259Sdim  unsigned TBAAID = getMDKindID("tbaa");
41249259Sdim  assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;
42249259Sdim
43249259Sdim  // Create the 'prof' metadata kind.
44249259Sdim  unsigned ProfID = getMDKindID("prof");
45249259Sdim  assert(ProfID == MD_prof && "prof kind id drifted"); (void)ProfID;
46249259Sdim
47249259Sdim  // Create the 'fpmath' metadata kind.
48249259Sdim  unsigned FPAccuracyID = getMDKindID("fpmath");
49249259Sdim  assert(FPAccuracyID == MD_fpmath && "fpmath kind id drifted");
50249259Sdim  (void)FPAccuracyID;
51249259Sdim
52249259Sdim  // Create the 'range' metadata kind.
53249259Sdim  unsigned RangeID = getMDKindID("range");
54249259Sdim  assert(RangeID == MD_range && "range kind id drifted");
55249259Sdim  (void)RangeID;
56249259Sdim
57249259Sdim  // Create the 'tbaa.struct' metadata kind.
58249259Sdim  unsigned TBAAStructID = getMDKindID("tbaa.struct");
59249259Sdim  assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
60249259Sdim  (void)TBAAStructID;
61249259Sdim
62249259Sdim  // Create the 'invariant.load' metadata kind.
63249259Sdim  unsigned InvariantLdId = getMDKindID("invariant.load");
64249259Sdim  assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
65249259Sdim  (void)InvariantLdId;
66249259Sdim}
67249259SdimLLVMContext::~LLVMContext() { delete pImpl; }
68249259Sdim
69249259Sdimvoid LLVMContext::addModule(Module *M) {
70249259Sdim  pImpl->OwnedModules.insert(M);
71249259Sdim}
72249259Sdim
73249259Sdimvoid LLVMContext::removeModule(Module *M) {
74249259Sdim  pImpl->OwnedModules.erase(M);
75249259Sdim}
76249259Sdim
77249259Sdim//===----------------------------------------------------------------------===//
78249259Sdim// Recoverable Backend Errors
79249259Sdim//===----------------------------------------------------------------------===//
80249259Sdim
81249259Sdimvoid LLVMContext::
82249259SdimsetInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
83249259Sdim                              void *DiagContext) {
84249259Sdim  pImpl->InlineAsmDiagHandler = DiagHandler;
85249259Sdim  pImpl->InlineAsmDiagContext = DiagContext;
86249259Sdim}
87249259Sdim
88249259Sdim/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
89249259Sdim/// setInlineAsmDiagnosticHandler.
90249259SdimLLVMContext::InlineAsmDiagHandlerTy
91249259SdimLLVMContext::getInlineAsmDiagnosticHandler() const {
92249259Sdim  return pImpl->InlineAsmDiagHandler;
93249259Sdim}
94249259Sdim
95249259Sdim/// getInlineAsmDiagnosticContext - Return the diagnostic context set by
96249259Sdim/// setInlineAsmDiagnosticHandler.
97249259Sdimvoid *LLVMContext::getInlineAsmDiagnosticContext() const {
98249259Sdim  return pImpl->InlineAsmDiagContext;
99249259Sdim}
100249259Sdim
101249259Sdimvoid LLVMContext::emitError(const Twine &ErrorStr) {
102249259Sdim  emitError(0U, ErrorStr);
103249259Sdim}
104249259Sdim
105249259Sdimvoid LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
106249259Sdim  unsigned LocCookie = 0;
107249259Sdim  if (const MDNode *SrcLoc = I->getMetadata("srcloc")) {
108249259Sdim    if (SrcLoc->getNumOperands() != 0)
109249259Sdim      if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
110249259Sdim        LocCookie = CI->getZExtValue();
111249259Sdim  }
112249259Sdim  return emitError(LocCookie, ErrorStr);
113249259Sdim}
114249259Sdim
115249259Sdimvoid LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
116249259Sdim  // If there is no error handler installed, just print the error and exit.
117249259Sdim  if (pImpl->InlineAsmDiagHandler == 0) {
118249259Sdim    errs() << "error: " << ErrorStr << "\n";
119249259Sdim    exit(1);
120249259Sdim  }
121249259Sdim
122249259Sdim  // If we do have an error handler, we can report the error and keep going.
123249259Sdim  SMDiagnostic Diag("", SourceMgr::DK_Error, ErrorStr.str());
124249259Sdim
125249259Sdim  pImpl->InlineAsmDiagHandler(Diag, pImpl->InlineAsmDiagContext, LocCookie);
126249259Sdim}
127249259Sdim
128249259Sdim//===----------------------------------------------------------------------===//
129249259Sdim// Metadata Kind Uniquing
130249259Sdim//===----------------------------------------------------------------------===//
131249259Sdim
132249259Sdim#ifndef NDEBUG
133249259Sdim/// isValidName - Return true if Name is a valid custom metadata handler name.
134249259Sdimstatic bool isValidName(StringRef MDName) {
135249259Sdim  if (MDName.empty())
136249259Sdim    return false;
137249259Sdim
138249259Sdim  if (!std::isalpha(static_cast<unsigned char>(MDName[0])))
139249259Sdim    return false;
140249259Sdim
141249259Sdim  for (StringRef::iterator I = MDName.begin() + 1, E = MDName.end(); I != E;
142249259Sdim       ++I) {
143249259Sdim    if (!std::isalnum(static_cast<unsigned char>(*I)) && *I != '_' &&
144249259Sdim        *I != '-' && *I != '.')
145249259Sdim      return false;
146249259Sdim  }
147249259Sdim  return true;
148249259Sdim}
149249259Sdim#endif
150249259Sdim
151249259Sdim/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
152249259Sdimunsigned LLVMContext::getMDKindID(StringRef Name) const {
153249259Sdim  assert(isValidName(Name) && "Invalid MDNode name");
154249259Sdim
155249259Sdim  // If this is new, assign it its ID.
156249259Sdim  return
157249259Sdim    pImpl->CustomMDKindNames.GetOrCreateValue(
158249259Sdim      Name, pImpl->CustomMDKindNames.size()).second;
159249259Sdim}
160249259Sdim
161249259Sdim/// getHandlerNames - Populate client supplied smallvector using custome
162249259Sdim/// metadata name and ID.
163249259Sdimvoid LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
164249259Sdim  Names.resize(pImpl->CustomMDKindNames.size());
165249259Sdim  for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),
166249259Sdim       E = pImpl->CustomMDKindNames.end(); I != E; ++I)
167249259Sdim    Names[I->second] = I->first();
168249259Sdim}
169