diff options
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
| -rw-r--r-- | lib/CodeGen/CGVTables.cpp | 38 | 
1 files changed, 35 insertions, 3 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 64b6d0d3fe9f5..2d9bf3bce926a 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -14,11 +14,12 @@  #include "CGCXXABI.h"  #include "CodeGenFunction.h"  #include "CodeGenModule.h" -#include "clang/CodeGen/ConstantInitBuilder.h"  #include "clang/AST/CXXInheritance.h"  #include "clang/AST/RecordLayout.h"  #include "clang/CodeGen/CGFunctionInfo.h" +#include "clang/CodeGen/ConstantInitBuilder.h"  #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/IR/IntrinsicInst.h"  #include "llvm/Support/Format.h"  #include "llvm/Transforms/Utils/Cloning.h"  #include <algorithm> @@ -50,7 +51,7 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,  static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,                                 const ThunkInfo &Thunk, llvm::Function *Fn) { -  CGM.setGlobalVisibility(Fn, MD); +  CGM.setGlobalVisibility(Fn, MD, ForDefinition);  }  static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, @@ -122,6 +123,33 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,    return RValue::get(ReturnValue);  } +/// This function clones a function's DISubprogram node and enters it into  +/// a value map with the intent that the map can be utilized by the cloner +/// to short-circuit Metadata node mapping. +/// Furthermore, the function resolves any DILocalVariable nodes referenced +/// by dbg.value intrinsics so they can be properly mapped during cloning. +static void resolveTopLevelMetadata(llvm::Function *Fn, +                                    llvm::ValueToValueMapTy &VMap) { +  // Clone the DISubprogram node and put it into the Value map. +  auto *DIS = Fn->getSubprogram(); +  if (!DIS) +    return; +  auto *NewDIS = DIS->replaceWithDistinct(DIS->clone()); +  VMap.MD()[DIS].reset(NewDIS); + +  // Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes +  // they are referencing. +  for (auto &BB : Fn->getBasicBlockList()) { +    for (auto &I : BB) { +      if (auto *DII = dyn_cast<llvm::DbgInfoIntrinsic>(&I)) { +        auto *DILocal = DII->getVariable(); +        if (!DILocal->isResolved()) +          DILocal->resolve(); +      } +    } +  } +} +  // This function does roughly the same thing as GenerateThunk, but in a  // very different way, so that va_start and va_end work correctly.  // FIXME: This function assumes "this" is the first non-sret LLVM argument of @@ -154,6 +182,10 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,    // Clone to thunk.    llvm::ValueToValueMapTy VMap; + +  // We are cloning a function while some Metadata nodes are still unresolved. +  // Ensure that the value mapper does not encounter any of them. +  resolveTopLevelMetadata(BaseFn, VMap);    llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);    Fn->replaceAllUsesWith(NewFn);    NewFn->takeName(Fn); @@ -698,7 +730,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,    // Create the variable that will hold the construction vtable.    llvm::GlobalVariable *VTable =      CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage); -  CGM.setGlobalVisibility(VTable, RD); +  CGM.setGlobalVisibility(VTable, RD, ForDefinition);    // V-tables are always unnamed_addr.    VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);  | 
