Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -630,32 +630,6 @@ AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew); } - // FIXME: Once this is working, then enable flag will change to a target - // check for whether the frame is large enough to want to use virtual - // frame index registers. Functions which don't want/need this optimization - // will continue to use the existing code path. - if (MFI->getUseLocalStackAllocationBlock()) { - unsigned Align = MFI->getLocalFrameMaxAlign(); - - // Adjust to alignment boundary. - Offset = RoundUpToAlignment(Offset, Align, Skew); - - DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); - - // Resolve offsets for objects in the local block. - for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { - std::pair Entry = MFI->getLocalFrameObjectMap(i); - int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; - DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << - FIOffset << "]\n"); - MFI->setObjectOffset(Entry.first, FIOffset); - } - // Allocate the local block - Offset += MFI->getLocalFrameSize(); - - MaxAlign = std::max(Align, MaxAlign); - } - // Make sure that the stack protector comes before the local variables on the // stack. SmallSet ProtectedObjs; @@ -705,6 +679,32 @@ Offset, MaxAlign, Skew); } + // FIXME: Once this is working, then enable flag will change to a target + // check for whether the frame is large enough to want to use virtual + // frame index registers. Functions which don't want/need this optimization + // will continue to use the existing code path. + if (MFI->getUseLocalStackAllocationBlock()) { + unsigned Align = MFI->getLocalFrameMaxAlign(); + + // Adjust to alignment boundary. + Offset = RoundUpToAlignment(Offset, Align, Skew); + + DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); + + // Resolve offsets for objects in the local block. + for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { + std::pair Entry = MFI->getLocalFrameObjectMap(i); + int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; + DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << + FIOffset << "]\n"); + MFI->setObjectOffset(Entry.first, FIOffset); + } + // Allocate the local block + Offset += MFI->getLocalFrameSize(); + + MaxAlign = std::max(Align, MaxAlign); + } + // Then assign frame offsets to stack objects that are not used to spill // callee saved registers. for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { Index: test/CodeGen/AArch64/stack-guard-vaarg.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/stack-guard-vaarg.ll @@ -0,0 +1,53 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux" + +%struct.__va_list = type { i8*, i8*, i8*, i32, i32 } + +; CHECK-LABEL: test +; CHECK: ldr [[GUARD:x[0-9]+]]{{.*}}:lo12:__stack_chk_guard +; Make sure the canary is placed relative to the frame pointer, not +; the stack pointer. +; CHECK: stur [[GUARD]], [x29, + +; Function Attrs: nounwind ssp +define void @test(i8* %i, ...) #0 { +entry: + %buf = alloca [10 x i8], align 1 + %ap = alloca %struct.__va_list, align 8 + %tmp = alloca %struct.__va_list, align 8 + %0 = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0 + call void @llvm.lifetime.start(i64 10, i8* %0) + %1 = bitcast %struct.__va_list* %ap to i8* + call void @llvm.lifetime.start(i64 32, i8* %1) + call void @llvm.va_start(i8* %1) + %2 = bitcast %struct.__va_list* %tmp to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 32, i32 8, i1 false) + call void @baz(i8* %i, %struct.__va_list* nonnull %tmp) + call void @bar(i8* %0) + call void @llvm.va_end(i8* %1) + call void @llvm.lifetime.end(i64 32, i8* %1) + call void @llvm.lifetime.end(i64 10, i8* %0) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) + +; Function Attrs: nounwind +declare void @llvm.va_start(i8*) + +declare void @baz(i8*, %struct.__va_list*) + +; Function Attrs: argmemonly nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) + +declare void @bar(i8*) + +; Function Attrs: nounwind +declare void @llvm.va_end(i8*) + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) + +attributes #0 = { ssp }