Skip to content

Instantly share code, notes, and snippets.

@ewokhias
Last active June 22, 2017 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ewokhias/3ec3eb19d5d3a7c1cba5ce58e5040d8c to your computer and use it in GitHub Desktop.
Save ewokhias/3ec3eb19d5d3a7c1cba5ce58e5040d8c to your computer and use it in GitHub Desktop.
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index ac1a133..24facd9 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -1158,9 +1158,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
PGO.assignRegionCounters(GD, CurFn);
if (isa<CXXDestructorDecl>(FD))
EmitDestructorBody(Args);
- else if (isa<CXXConstructorDecl>(FD))
- EmitConstructorBody(Args);
- else if (getLangOpts().CUDA &&
+ else if (isa<CXXConstructorDecl>(FD)) {
+ EmitConstructorBody(Args);
+ llvm::MDNode* MetadataNode =llvm::MDNode::get(Fn->getContext(), llvm::MDString::get(Fn->getContext(), "constructor"));
+ Fn->setMetadata("constructor_mark", MetadataNode);
+ } else if (getLangOpts().CUDA &&
!getLangOpts().CUDAIsDevice &&
FD->hasAttr<CUDAGlobalAttr>())
CGM.getCUDARuntime().emitDeviceStub(*this, Args);
$ ../../llvm/build/debug/bin/llc test.ll
inlinable function call in a function with debug info must have a !dbg location
call void @_ZN12MyFunnyClassC2EvCloned(%struct.MyFunnyClass* %0)
../../llvm/build/debug/bin/llc: test.ll: error: input module is broken!
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <llvm/IR/Operator.h>
#include <llvm/IR/Module.h>
#include "llvm/IR/IRBuilder.h"
#include <llvm/Support/raw_os_ostream.h>
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Transforms/Utils/Cloning.h"
using namespace llvm;
namespace {
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
if (F.getMetadata("constructor_mark")) {
Module *M = F.getParent();
const llvm::FunctionType *OldFTy = F.getFunctionType();
std::vector<Type *> Params(OldFTy->param_begin(), OldFTy->param_end());
FunctionType *NewFTy = FunctionType::get(F.getReturnType(), ArrayRef<Type *>(Params),
OldFTy->isVarArg());
ValueToValueMapTy Map;
ClonedCodeInfo *CI;
Function *NF = Function::Create(NewFTy, F.getLinkage(), F.getName() + "Cloned", F.getParent());
SmallVector<ReturnInst *, 8> Returns;
Function::arg_iterator DestI = NF->arg_begin();
for (const Argument &I : F.args()) {
DestI->setName(I.getName());
Map[&I] = &*DestI++;
}
CloneFunctionInto(NF, &F, Map, true, Returns, "Cloned");
NF->setMetadata("constructor_mark", NULL);
errs() << "Cloned Function " << F.getName() << ". New name is " << NF->getName() << "\n";
replaceCallSites(&F, NF);
errs() << "Call sites replaced\n";
return true;
}
return false;
}
void replaceCallSites(Function *Old, Function *New) {
Module *Module = Old->getParent();
while (!Old->use_empty()) {
llvm::CallSite CS(Old->user_back());
llvm::Instruction *Call = CS.getInstruction();
llvm::Function *CallingF = Call->getParent()->getParent();
std::vector<llvm::Value *> Args;
Args.reserve(CS.arg_size());
llvm::CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
for (unsigned i = 0, e = Old->getFunctionType()->getNumParams(); i != e; ++i, ++AI) {
llvm::Value *v = *AI;
Args.push_back(v);
}
llvm::Instruction *Before = Call;
if (llvm::InvokeInst *II = llvm::dyn_cast<llvm::InvokeInst>(Call)) {
llvm::InvokeInst *Invoke;
Invoke = llvm::InvokeInst::Create(New, II->getNormalDest(), II->getUnwindDest(),
ArrayRef<Value *>(Args), "",
Before);
Invoke->setCallingConv(CS.getCallingConv());
} else {
CallInst *CallInst;
CallInst = CallInst::Create(New, ArrayRef<Value *>(Args), "", Before);
CallInst->setCallingConv(CS.getCallingConv());
if (CallInst->isTailCall()) {
CallInst->setTailCall();
}
}
errs() << "Unlinking call " << Call->getName() << "\n";
Call->eraseFromParent();
}
}
};
}
char SkeletonPass::ID = 0;
// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses
RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
struct MyFunnyClass {
virtual int overridden_function() {
return 5;
};
virtual void second_function() {};
virtual void third_function() {};
};
int main() {
MyFunnyClass *obj = new MyFunnyClass();
return obj->overridden_function();
}
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%struct.MyFunnyClass = type { i32 (...)** }
$_ZN12MyFunnyClassC2Ev = comdat any
$_ZN12MyFunnyClass19overridden_functionEv = comdat any
$_ZN12MyFunnyClass15second_functionEv = comdat any
$_ZN12MyFunnyClass14third_functionEv = comdat any
$_ZTV12MyFunnyClass = comdat any
$_ZTS12MyFunnyClass = comdat any
$_ZTI12MyFunnyClass = comdat any
@_ZTV12MyFunnyClass = linkonce_odr unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI12MyFunnyClass to i8*), i8* bitcast (i32 (%struct.MyFunnyClass*)* @_ZN12MyFunnyC$
@_ZTVN10__cxxabiv117__class_type_infoE = external global i8*
@_ZTS12MyFunnyClass = linkonce_odr constant [15 x i8] c"12MyFunnyClass\00", comdat
@_ZTI12MyFunnyClass = linkonce_odr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([15 x i8], $
; Function Attrs: noinline norecurse optnone uwtable
define i32 @main() #0 !dbg !7 {
entry:
%retval = alloca i32, align 4
%obj = alloca %struct.MyFunnyClass*, align 8
store i32 0, i32* %retval, align 4
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %obj, metadata !11, metadata !26), !dbg !27
%call = call i8* @_Znwm(i64 8) #5, !dbg !28
%0 = bitcast i8* %call to %struct.MyFunnyClass*, !dbg !28
%1 = bitcast %struct.MyFunnyClass* %0 to i8*, !dbg !29
call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 8, i32 8, i1 false), !dbg !29
call void @_ZN12MyFunnyClassC2EvCloned(%struct.MyFunnyClass* %0)
store %struct.MyFunnyClass* %0, %struct.MyFunnyClass** %obj, align 8, !dbg !27
%2 = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %obj, align 8, !dbg !30
%3 = bitcast %struct.MyFunnyClass* %2 to i32 (%struct.MyFunnyClass*)***, !dbg !31
%vtable = load i32 (%struct.MyFunnyClass*)**, i32 (%struct.MyFunnyClass*)*** %3, align 8, !dbg !31
%vfn = getelementptr inbounds i32 (%struct.MyFunnyClass*)*, i32 (%struct.MyFunnyClass*)** %vtable, i64 0, !dbg !31
%4 = load i32 (%struct.MyFunnyClass*)*, i32 (%struct.MyFunnyClass*)** %vfn, align 8, !dbg !31
%call1 = call i32 %4(%struct.MyFunnyClass* %2), !dbg !31
ret i32 %call1, !dbg !32
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: nobuiltin
declare noalias i8* @_Znwm(i64) #2
; Function Attrs: argmemonly nounwind
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #3
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr void @_ZN12MyFunnyClassC2Ev(%struct.MyFunnyClass* %this) unnamed_addr #4 comdat align 2 !dbg !33 !constructor_mark !35 {
entry:
%this.addr = alloca %struct.MyFunnyClass*, align 8
store %struct.MyFunnyClass* %this, %struct.MyFunnyClass** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %this.addr, metadata !36, metadata !26), !dbg !37
%this1 = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %this.addr, align 8
%0 = bitcast %struct.MyFunnyClass* %this1 to i32 (...)***, !dbg !38
store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV12MyFunnyClass, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8, !dbg !38
ret void, !dbg !38
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr i32 @_ZN12MyFunnyClass19overridden_functionEv(%struct.MyFunnyClass* %this) unnamed_addr #4 comdat align 2 !dbg !39 {
entry:
%this.addr = alloca %struct.MyFunnyClass*, align 8
store %struct.MyFunnyClass* %this, %struct.MyFunnyClass** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %this.addr, metadata !40, metadata !26), !dbg !41
%this1 = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %this.addr, align 8
ret i32 5, !dbg !42
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr void @_ZN12MyFunnyClass15second_functionEv(%struct.MyFunnyClass* %this) unnamed_addr #4 comdat align 2 !dbg !43 {
entry:
%this.addr = alloca %struct.MyFunnyClass*, align 8
store %struct.MyFunnyClass* %this, %struct.MyFunnyClass** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %this.addr, metadata !44, metadata !26), !dbg !45
%this1 = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %this.addr, align 8
ret void, !dbg !46
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr void @_ZN12MyFunnyClass14third_functionEv(%struct.MyFunnyClass* %this) unnamed_addr #4 comdat align 2 !dbg !47 {
entry:
%this.addr = alloca %struct.MyFunnyClass*, align 8
store %struct.MyFunnyClass* %this, %struct.MyFunnyClass** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %this.addr, metadata !48, metadata !26), !dbg !49
%this1 = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %this.addr, align 8
ret void, !dbg !50
}
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr void @_ZN12MyFunnyClassC2EvCloned(%struct.MyFunnyClass* %this) unnamed_addr #4 align 2 !dbg !51 {
entryCloned:
%this.addrCloned = alloca %struct.MyFunnyClass*, align 8
store %struct.MyFunnyClass* %this, %struct.MyFunnyClass** %this.addrCloned, align 8
call void @llvm.dbg.declare(metadata %struct.MyFunnyClass** %this.addrCloned, metadata !61, metadata !26), !dbg !63
%this1Cloned = load %struct.MyFunnyClass*, %struct.MyFunnyClass** %this.addrCloned, align 8
%0 = bitcast %struct.MyFunnyClass* %this1Cloned to i32 (...)***, !dbg !64
store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV12MyFunnyClass, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %0, align 8, !dbg !64
ret void, !dbg !64
}
attributes #0 = { noinline norecurse optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointe$
attributes #1 = { nounwind readnone speculatable }
attributes #2 = { nobuiltin "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs$
attributes #3 = { argmemonly nounwind }
attributes #4 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer$
attributes #5 = { builtin }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (https://bitbucket.org/sbspraktikum/clang.git 6adac51dabb51771aade9b29f059f562b7f457c3) (https://bitbucke$
!1 = !DIFile(filename: "test.cpp", directory: "/home/mbernad/playground/cpptest")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!"clang version 5.0.0 (https://bitbucket.org/sbspraktikum/clang.git 6adac51dabb51771aade9b29f059f562b7f457c3) (https://bitbucket.org/sbspraktikum/llvm.git 470c6959b7834acd5191390007439eaf95b087a6)"}
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 9, type: !8, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!8 = !DISubroutineType(types: !9)
!9 = !{!10}
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !DILocalVariable(name: "obj", scope: !7, file: !1, line: 10, type: !12)
!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyFunnyClass", file: !1, line: 1, size: 64, elements: !14, vtableHolder: !13, identifier: "_ZTS12MyFunnyClass")
!14 = !{!15, !18, !22, !25}
!15 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyFunnyClass", scope: !1, file: !1, baseType: !16, size: 64, flags: DIFlagArtificial)
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
!17 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !8, size: 64)
!18 = !DISubprogram(name: "overridden_function", linkageName: "_ZN12MyFunnyClass19overridden_functionEv", scope: !13, file: !1, line: 2, type: !19, isLocal: false, isDefinition: false, scopeLine: 2, contain$
!19 = !DISubroutineType(types: !20)
!20 = !{!10, !21}
!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!22 = !DISubprogram(name: "second_function", linkageName: "_ZN12MyFunnyClass15second_functionEv", scope: !13, file: !1, line: 5, type: !23, isLocal: false, isDefinition: false, scopeLine: 5, containingType:$
!23 = !DISubroutineType(types: !24)
!24 = !{null, !21}
!25 = !DISubprogram(name: "third_function", linkageName: "_ZN12MyFunnyClass14third_functionEv", scope: !13, file: !1, line: 6, type: !23, isLocal: false, isDefinition: false, scopeLine: 6, containingType: !$
!26 = !DIExpression()
!27 = !DILocation(line: 10, column: 23, scope: !7)
!28 = !DILocation(line: 10, column: 29, scope: !7)
!29 = !DILocation(line: 10, column: 33, scope: !7)
!30 = !DILocation(line: 11, column: 16, scope: !7)
!31 = !DILocation(line: 11, column: 21, scope: !7)
!32 = !DILocation(line: 11, column: 9, scope: !7)
!33 = distinct !DISubprogram(name: "MyFunnyClass", linkageName: "_ZN12MyFunnyClassC2Ev", scope: !13, file: !1, line: 1, type: !23, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagArtificial |$
!34 = !DISubprogram(name: "MyFunnyClass", scope: !13, type: !23, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
!35 = !{!"constructor"}
!36 = !DILocalVariable(name: "this", arg: 1, scope: !33, type: !12, flags: DIFlagArtificial | DIFlagObjectPointer)
!37 = !DILocation(line: 0, scope: !33)
!38 = !DILocation(line: 1, column: 8, scope: !33)
!39 = distinct !DISubprogram(name: "overridden_function", linkageName: "_ZN12MyFunnyClass19overridden_functionEv", scope: !13, file: !1, line: 2, type: !19, isLocal: false, isDefinition: true, scopeLine: 2,$
!40 = !DILocalVariable(name: "this", arg: 1, scope: !39, type: !12, flags: DIFlagArtificial | DIFlagObjectPointer)
!41 = !DILocation(line: 0, scope: !39)
!42 = !DILocation(line: 3, column: 17, scope: !39)
!43 = distinct !DISubprogram(name: "second_function", linkageName: "_ZN12MyFunnyClass15second_functionEv", scope: !13, file: !1, line: 5, type: !23, isLocal: false, isDefinition: true, scopeLine: 5, flags: $
!44 = !DILocalVariable(name: "this", arg: 1, scope: !43, type: !12, flags: DIFlagArtificial | DIFlagObjectPointer)
!45 = !DILocation(line: 0, scope: !43)
!46 = !DILocation(line: 5, column: 41, scope: !43)
!47 = distinct !DISubprogram(name: "third_function", linkageName: "_ZN12MyFunnyClass14third_functionEv", scope: !13, file: !1, line: 6, type: !23, isLocal: false, isDefinition: true, scopeLine: 6, flags: DI$
!48 = !DILocalVariable(name: "this", arg: 1, scope: !47, type: !12, flags: DIFlagArtificial | DIFlagObjectPointer)
!49 = !DILocation(line: 0, scope: !47)
!50 = !DILocation(line: 6, column: 40, scope: !47)
!51 = distinct !DISubprogram(name: "MyFunnyClass", linkageName: "_ZN12MyFunnyClassC2Ev", scope: !52, file: !1, line: 1, type: !23, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagArtificial |$
!52 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyFunnyClass", file: !1, line: 1, size: 64, elements: !53, vtableHolder: !52, identifier: "_ZTS12MyFunnyClass")
!53 = !{!15, !54, !58, !59}
!54 = !DISubprogram(name: "overridden_function", linkageName: "_ZN12MyFunnyClass19overridden_functionEv", scope: !52, file: !1, line: 2, type: !55, isLocal: false, isDefinition: false, scopeLine: 2, contain$
!55 = !DISubroutineType(types: !56)
!56 = !{!10, !57}
!57 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !52, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!58 = !DISubprogram(name: "second_function", linkageName: "_ZN12MyFunnyClass15second_functionEv", scope: !52, file: !1, line: 5, type: !23, isLocal: false, isDefinition: false, scopeLine: 5, containingType:$
!59 = !DISubprogram(name: "third_function", linkageName: "_ZN12MyFunnyClass14third_functionEv", scope: !52, file: !1, line: 6, type: !23, isLocal: false, isDefinition: false, scopeLine: 6, containingType: !$
!60 = !DISubprogram(name: "MyFunnyClass", scope: !52, type: !23, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
!61 = !DILocalVariable(name: "this", arg: 1, scope: !51, type: !62, flags: DIFlagArtificial | DIFlagObjectPointer)
!62 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !52, size: 64)
!63 = !DILocation(line: 0, scope: !51)
!64 = !DILocation(line: 1, column: 8, scope: !51)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment