forked from OSchip/llvm-project
Fix for PR33930. Short-circuit metadata mapping when cloning a varargs thunk.
The cloning happens before all metadata nodes are resolved. Prevent the value mapper from running into unresolved or temporary MD nodes. Differential Revision: https://reviews.llvm.org/D39396 llvm-svn: 317047
This commit is contained in:
parent
aedb4bf37f
commit
a347c47f5d
|
@ -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>
|
||||
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// REQUIRES: asserts
|
||||
// RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm %s -o - | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
// This test simply checks that the varargs thunk is created. The failing test
|
||||
// case asserts.
|
||||
|
||||
struct Alpha {
|
||||
virtual void bravo(...);
|
||||
};
|
||||
struct Charlie {
|
||||
virtual ~Charlie() {}
|
||||
};
|
||||
struct CharlieImpl : Charlie, Alpha {
|
||||
void bravo(...) {}
|
||||
} delta;
|
||||
|
||||
// CHECK: define {{.*}} void @_ZThn8_N11CharlieImpl5bravoEz(
|
|
@ -0,0 +1,33 @@
|
|||
// REQUIRES: asserts
|
||||
// RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm %s -o - | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
// This test simply checks that the varargs thunk is created. The failing test
|
||||
// case asserts.
|
||||
|
||||
typedef signed char __int8_t;
|
||||
typedef int BOOL;
|
||||
class CMsgAgent;
|
||||
|
||||
class CFs {
|
||||
public:
|
||||
typedef enum {} CACHE_HINT;
|
||||
virtual BOOL ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... ) ;
|
||||
};
|
||||
|
||||
typedef struct {} _Lldiv_t;
|
||||
|
||||
class CBdVfs {
|
||||
public:
|
||||
virtual ~CBdVfs( ) {}
|
||||
};
|
||||
|
||||
class CBdVfsImpl : public CBdVfs, public CFs {
|
||||
BOOL ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... );
|
||||
};
|
||||
|
||||
BOOL CBdVfsImpl::ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// CHECK: define {{.*}} @_ZThn8_N10CBdVfsImpl12ReqCacheHintEP9CMsgAgentN3CFs10CACHE_HINTEz(
|
Loading…
Reference in New Issue