Summary: musttail calls should not require allocating extra stack for arguments. Updates to arguments passed in memory should happen in place before the epilogue. This bug was mostly a missed optimization, unless inalloca was used and store to push conversion fired. If a reserved call frame was used for an inalloca musttail call, the call setup and teardown instructions would be deleted, and SP adjustments would be inserted in the prologue and epilogue. You can see these are removed from several test cases in this change. In the case where the stack frame was not reserved, i.e. call frame optimization fires and turns argument stores into pushes, then the imbalanced call frame setup instructions created for inalloca calls become a problem. They remain in the instruction stream, resulting in a call setup that allocates zero bytes (expected for inalloca), and a call teardown that deallocates the inalloca pack. This deallocation was unbalanced, leading to subsequent crashes. Reviewers: hans Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D71097
39 lines
1.6 KiB
LLVM
39 lines
1.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc %s -o - | FileCheck %s
|
|
|
|
; Previously, we would accidentally leave behind SP adjustments to setup a call
|
|
; frame for the musttail call target, and SP adjustments would end up
|
|
; unbalanced. Reported as https://crbug.com/1026882.
|
|
|
|
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
|
target triple = "i386-pc-windows-msvc19.16.0"
|
|
|
|
; 20 bytes of memory.
|
|
%struct.Args = type { i32, i32, i32, i32, i32 }
|
|
|
|
declare dso_local x86_thiscallcc void @methodWithVtorDisp(i8* nocapture readonly, <{ %struct.Args }>* inalloca)
|
|
|
|
define dso_local x86_thiscallcc void @methodWithVtorDisp_thunk(i8* %0, <{ %struct.Args }>* inalloca %1) #0 {
|
|
; CHECK-LABEL: methodWithVtorDisp_thunk:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: pushl %esi
|
|
; CHECK-NEXT: movl %ecx, %esi
|
|
; CHECK-NEXT: subl -4(%ecx), %esi
|
|
; CHECK-NEXT: pushl {{[0-9]+}}(%esp)
|
|
; CHECK-NEXT: pushl $_methodWithVtorDisp_thunk
|
|
; CHECK-NEXT: calll ___cyg_profile_func_exit
|
|
; CHECK-NEXT: addl $8, %esp
|
|
; CHECK-NEXT: movl %esi, %ecx
|
|
; CHECK-NEXT: popl %esi
|
|
; CHECK-NEXT: jmp _methodWithVtorDisp # TAILCALL
|
|
%3 = getelementptr inbounds i8, i8* %0, i32 -4
|
|
%4 = bitcast i8* %3 to i32*
|
|
%5 = load i32, i32* %4, align 4
|
|
%6 = sub i32 0, %5
|
|
%7 = getelementptr i8, i8* %0, i32 %6
|
|
musttail call x86_thiscallcc void @methodWithVtorDisp(i8* %7, <{ %struct.Args }>* inalloca nonnull %1)
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { nounwind optsize "instrument-function-exit-inlined"="__cyg_profile_func_exit" }
|