1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

EntryExitInstrumenter: Handle musttail calls

Inserting instrumentation between a musttail call and ret instruction
would create invalid IR. Instead, treat musttail calls as function
exits.

llvm-svn: 329385
This commit is contained in:
Hans Wennborg 2018-04-06 10:14:09 +00:00
parent cc46df92b4
commit 22ceb3e983
2 changed files with 39 additions and 6 deletions

View File

@ -91,17 +91,27 @@ static bool runOnFunction(Function &F, bool PostInlining) {
if (!ExitFunc.empty()) {
for (BasicBlock &BB : F) {
TerminatorInst *T = BB.getTerminator();
Instruction *T = BB.getTerminator();
if (!isa<ReturnInst>(T))
continue;
// If T is preceded by a musttail call, that's the real terminator.
Instruction *Prev = T->getPrevNode();
if (BitCastInst *BCI = dyn_cast_or_null<BitCastInst>(Prev))
Prev = BCI->getPrevNode();
if (CallInst *CI = dyn_cast_or_null<CallInst>(Prev)) {
if (CI->isMustTailCall())
T = CI;
}
DebugLoc DL;
if (DebugLoc TerminatorDL = T->getDebugLoc())
DL = TerminatorDL;
else if (auto SP = F.getSubprogram())
DL = DebugLoc::get(0, 0, SP);
if (isa<ReturnInst>(T)) {
insertCall(F, ExitFunc, T, DL);
Changed = true;
}
insertCall(F, ExitFunc, T, DL);
Changed = true;
}
F.removeAttribute(AttributeList::FunctionIndex, ExitAttr);
}

View File

@ -44,7 +44,6 @@ entry:
; CHECK-NEXT ret void
}
attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
; The mcount function has many different names.
@ -78,10 +77,33 @@ define void @f7() #7 { entry: ret void }
; CHECK: call void @__cyg_profile_func_enter_bare
; Treat musttail calls as terminators; inserting between the musttail call and
; ret is not allowed.
declare i32* @tailcallee()
define i32* @tailcaller() #8 {
%1 = musttail call i32* @tailcallee()
ret i32* %1
; CHECK-LABEL: define i32* @tailcaller
; CHECK: call void @__cyg_profile_func_exit
; CHECK: musttail call i32* @tailcallee
; CHECK: ret
}
define i8* @tailcaller2() #8 {
%1 = musttail call i32* @tailcallee()
%2 = bitcast i32* %1 to i8*
ret i8* %2
; CHECK-LABEL: define i8* @tailcaller2
; CHECK: call void @__cyg_profile_func_exit
; CHECK: musttail call i32* @tailcallee
; CHECK: bitcast
; CHECK: ret
}
; The attributes are "consumed" when the instrumentation is inserted.
; CHECK: attributes
; CHECK-NOT: instrument-function
attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
attributes #1 = { "instrument-function-entry-inlined"=".mcount" }
attributes #2 = { "instrument-function-entry-inlined"="\01__gnu_mcount_nc" }
attributes #3 = { "instrument-function-entry-inlined"="\01_mcount" }
@ -89,3 +111,4 @@ attributes #4 = { "instrument-function-entry-inlined"="\01mcount" }
attributes #5 = { "instrument-function-entry-inlined"="__mcount" }
attributes #6 = { "instrument-function-entry-inlined"="_mcount" }
attributes #7 = { "instrument-function-entry-inlined"="__cyg_profile_func_enter_bare" }
attributes #8 = { "instrument-function-exit"="__cyg_profile_func_exit" }