Home | History | Annotate | Download | only in IR
      1 //===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
      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 implements LLVMContext, as a wrapper around the opaque
     11 //  class LLVMContextImpl.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/IR/LLVMContext.h"
     16 #include "llvm/ADT/SmallVector.h"
     17 #include "llvm/ADT/StringMap.h"
     18 #include "llvm/ADT/StringRef.h"
     19 #include "llvm/ADT/Twine.h"
     20 #include "LLVMContextImpl.h"
     21 #include "llvm/IR/DiagnosticInfo.h"
     22 #include "llvm/IR/DiagnosticPrinter.h"
     23 #include "llvm/IR/Metadata.h"
     24 #include "llvm/IR/Module.h"
     25 #include "llvm/Support/Casting.h"
     26 #include "llvm/Support/ErrorHandling.h"
     27 #include "llvm/Support/raw_ostream.h"
     28 #include <cassert>
     29 #include <cstdlib>
     30 #include <string>
     31 #include <utility>
     32 
     33 using namespace llvm;
     34 
     35 LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
     36   // Create the fixed metadata kinds. This is done in the same order as the
     37   // MD_* enum values so that they correspond.
     38 
     39   // Create the 'dbg' metadata kind.
     40   unsigned DbgID = getMDKindID("dbg");
     41   assert(DbgID == MD_dbg && "dbg kind id drifted"); (void)DbgID;
     42 
     43   // Create the 'tbaa' metadata kind.
     44   unsigned TBAAID = getMDKindID("tbaa");
     45   assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;
     46 
     47   // Create the 'prof' metadata kind.
     48   unsigned ProfID = getMDKindID("prof");
     49   assert(ProfID == MD_prof && "prof kind id drifted"); (void)ProfID;
     50 
     51   // Create the 'fpmath' metadata kind.
     52   unsigned FPAccuracyID = getMDKindID("fpmath");
     53   assert(FPAccuracyID == MD_fpmath && "fpmath kind id drifted");
     54   (void)FPAccuracyID;
     55 
     56   // Create the 'range' metadata kind.
     57   unsigned RangeID = getMDKindID("range");
     58   assert(RangeID == MD_range && "range kind id drifted");
     59   (void)RangeID;
     60 
     61   // Create the 'tbaa.struct' metadata kind.
     62   unsigned TBAAStructID = getMDKindID("tbaa.struct");
     63   assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
     64   (void)TBAAStructID;
     65 
     66   // Create the 'invariant.load' metadata kind.
     67   unsigned InvariantLdId = getMDKindID("invariant.load");
     68   assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
     69   (void)InvariantLdId;
     70 
     71   // Create the 'alias.scope' metadata kind.
     72   unsigned AliasScopeID = getMDKindID("alias.scope");
     73   assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted");
     74   (void)AliasScopeID;
     75 
     76   // Create the 'noalias' metadata kind.
     77   unsigned NoAliasID = getMDKindID("noalias");
     78   assert(NoAliasID == MD_noalias && "noalias kind id drifted");
     79   (void)NoAliasID;
     80 
     81   // Create the 'nontemporal' metadata kind.
     82   unsigned NonTemporalID = getMDKindID("nontemporal");
     83   assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted");
     84   (void)NonTemporalID;
     85 
     86   // Create the 'llvm.mem.parallel_loop_access' metadata kind.
     87   unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access");
     88   assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access &&
     89          "mem_parallel_loop_access kind id drifted");
     90   (void)MemParallelLoopAccessID;
     91 
     92   // Create the 'nonnull' metadata kind.
     93   unsigned NonNullID = getMDKindID("nonnull");
     94   assert(NonNullID == MD_nonnull && "nonnull kind id drifted");
     95   (void)NonNullID;
     96 
     97   // Create the 'dereferenceable' metadata kind.
     98   unsigned DereferenceableID = getMDKindID("dereferenceable");
     99   assert(DereferenceableID == MD_dereferenceable &&
    100          "dereferenceable kind id drifted");
    101   (void)DereferenceableID;
    102 
    103   // Create the 'dereferenceable_or_null' metadata kind.
    104   unsigned DereferenceableOrNullID = getMDKindID("dereferenceable_or_null");
    105   assert(DereferenceableOrNullID == MD_dereferenceable_or_null &&
    106          "dereferenceable_or_null kind id drifted");
    107   (void)DereferenceableOrNullID;
    108 
    109   // Create the 'make.implicit' metadata kind.
    110   unsigned MakeImplicitID = getMDKindID("make.implicit");
    111   assert(MakeImplicitID == MD_make_implicit &&
    112          "make.implicit kind id drifted");
    113   (void)MakeImplicitID;
    114 
    115   // Create the 'unpredictable' metadata kind.
    116   unsigned UnpredictableID = getMDKindID("unpredictable");
    117   assert(UnpredictableID == MD_unpredictable &&
    118          "unpredictable kind id drifted");
    119   (void)UnpredictableID;
    120 
    121   // Create the 'invariant.group' metadata kind.
    122   unsigned InvariantGroupId = getMDKindID("invariant.group");
    123   assert(InvariantGroupId == MD_invariant_group &&
    124          "invariant.group kind id drifted");
    125   (void)InvariantGroupId;
    126 
    127   // Create the 'align' metadata kind.
    128   unsigned AlignID = getMDKindID("align");
    129   assert(AlignID == MD_align && "align kind id drifted");
    130   (void)AlignID;
    131 
    132   // Create the 'llvm.loop' metadata kind.
    133   unsigned LoopID = getMDKindID("llvm.loop");
    134   assert(LoopID == MD_loop && "llvm.loop kind id drifted");
    135   (void)LoopID;
    136 
    137   unsigned TypeID = getMDKindID("type");
    138   assert(TypeID == MD_type && "type kind id drifted");
    139   (void)TypeID;
    140 
    141   auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt");
    142   assert(DeoptEntry->second == LLVMContext::OB_deopt &&
    143          "deopt operand bundle id drifted!");
    144   (void)DeoptEntry;
    145 
    146   auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
    147   assert(FuncletEntry->second == LLVMContext::OB_funclet &&
    148          "funclet operand bundle id drifted!");
    149   (void)FuncletEntry;
    150 
    151   auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");
    152   assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&
    153          "gc-transition operand bundle id drifted!");
    154   (void)GCTransitionEntry;
    155 }
    156 
    157 LLVMContext::~LLVMContext() { delete pImpl; }
    158 
    159 void LLVMContext::addModule(Module *M) {
    160   pImpl->OwnedModules.insert(M);
    161 }
    162 
    163 void LLVMContext::removeModule(Module *M) {
    164   pImpl->OwnedModules.erase(M);
    165 }
    166 
    167 //===----------------------------------------------------------------------===//
    168 // Recoverable Backend Errors
    169 //===----------------------------------------------------------------------===//
    170 
    171 void LLVMContext::
    172 setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
    173                               void *DiagContext) {
    174   pImpl->InlineAsmDiagHandler = DiagHandler;
    175   pImpl->InlineAsmDiagContext = DiagContext;
    176 }
    177 
    178 /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
    179 /// setInlineAsmDiagnosticHandler.
    180 LLVMContext::InlineAsmDiagHandlerTy
    181 LLVMContext::getInlineAsmDiagnosticHandler() const {
    182   return pImpl->InlineAsmDiagHandler;
    183 }
    184 
    185 /// getInlineAsmDiagnosticContext - Return the diagnostic context set by
    186 /// setInlineAsmDiagnosticHandler.
    187 void *LLVMContext::getInlineAsmDiagnosticContext() const {
    188   return pImpl->InlineAsmDiagContext;
    189 }
    190 
    191 void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
    192                                        void *DiagnosticContext,
    193                                        bool RespectFilters) {
    194   pImpl->DiagnosticHandler = DiagnosticHandler;
    195   pImpl->DiagnosticContext = DiagnosticContext;
    196   pImpl->RespectDiagnosticFilters = RespectFilters;
    197 }
    198 
    199 LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
    200   return pImpl->DiagnosticHandler;
    201 }
    202 
    203 void *LLVMContext::getDiagnosticContext() const {
    204   return pImpl->DiagnosticContext;
    205 }
    206 
    207 void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)
    208 {
    209   pImpl->YieldCallback = Callback;
    210   pImpl->YieldOpaqueHandle = OpaqueHandle;
    211 }
    212 
    213 void LLVMContext::yield() {
    214   if (pImpl->YieldCallback)
    215     pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);
    216 }
    217 
    218 void LLVMContext::emitError(const Twine &ErrorStr) {
    219   diagnose(DiagnosticInfoInlineAsm(ErrorStr));
    220 }
    221 
    222 void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
    223   assert (I && "Invalid instruction");
    224   diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
    225 }
    226 
    227 static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
    228   // Optimization remarks are selective. They need to check whether the regexp
    229   // pattern, passed via one of the -pass-remarks* flags, matches the name of
    230   // the pass that is emitting the diagnostic. If there is no match, ignore the
    231   // diagnostic and return.
    232   if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
    233     return Remark->isEnabled();
    234 
    235   return true;
    236 }
    237 
    238 const char *
    239 LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
    240   switch (Severity) {
    241   case DS_Error:
    242     return "error";
    243   case DS_Warning:
    244     return "warning";
    245   case DS_Remark:
    246     return "remark";
    247   case DS_Note:
    248     return "note";
    249   }
    250   llvm_unreachable("Unknown DiagnosticSeverity");
    251 }
    252 
    253 void LLVMContext::diagnose(const DiagnosticInfo &DI) {
    254   // If there is a report handler, use it.
    255   if (pImpl->DiagnosticHandler) {
    256     if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI))
    257       pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
    258     return;
    259   }
    260 
    261   if (!isDiagnosticEnabled(DI))
    262     return;
    263 
    264   // Otherwise, print the message with a prefix based on the severity.
    265   DiagnosticPrinterRawOStream DP(errs());
    266   errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
    267   DI.print(DP);
    268   errs() << "\n";
    269   if (DI.getSeverity() == DS_Error)
    270     exit(1);
    271 }
    272 
    273 void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
    274   diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
    275 }
    276 
    277 //===----------------------------------------------------------------------===//
    278 // Metadata Kind Uniquing
    279 //===----------------------------------------------------------------------===//
    280 
    281 /// Return a unique non-zero ID for the specified metadata kind.
    282 unsigned LLVMContext::getMDKindID(StringRef Name) const {
    283   // If this is new, assign it its ID.
    284   return pImpl->CustomMDKindNames.insert(
    285                                      std::make_pair(
    286                                          Name, pImpl->CustomMDKindNames.size()))
    287       .first->second;
    288 }
    289 
    290 /// getHandlerNames - Populate client-supplied smallvector using custom
    291 /// metadata name and ID.
    292 void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
    293   Names.resize(pImpl->CustomMDKindNames.size());
    294   for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),
    295        E = pImpl->CustomMDKindNames.end(); I != E; ++I)
    296     Names[I->second] = I->first();
    297 }
    298 
    299 void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
    300   pImpl->getOperandBundleTags(Tags);
    301 }
    302 
    303 uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
    304   return pImpl->getOperandBundleTagID(Tag);
    305 }
    306 
    307 void LLVMContext::setGC(const Function &Fn, std::string GCName) {
    308   auto It = pImpl->GCNames.find(&Fn);
    309 
    310   if (It == pImpl->GCNames.end()) {
    311     pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
    312     return;
    313   }
    314   It->second = std::move(GCName);
    315 }
    316 
    317 const std::string &LLVMContext::getGC(const Function &Fn) {
    318   return pImpl->GCNames[&Fn];
    319 }
    320 
    321 void LLVMContext::deleteGC(const Function &Fn) {
    322   pImpl->GCNames.erase(&Fn);
    323 }
    324 
    325 bool LLVMContext::shouldDiscardValueNames() const {
    326   return pImpl->DiscardValueNames;
    327 }
    328 
    329 bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; }
    330 
    331 void LLVMContext::enableDebugTypeODRUniquing() {
    332   if (pImpl->DITypeMap)
    333     return;
    334 
    335   pImpl->DITypeMap.emplace();
    336 }
    337 
    338 void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }
    339 
    340 void LLVMContext::setDiscardValueNames(bool Discard) {
    341   pImpl->DiscardValueNames = Discard;
    342 }
    343 
    344 OptBisect &LLVMContext::getOptBisect() {
    345   return pImpl->getOptBisect();
    346 }
    347