Skip to content

Backport several commits for windows arm64 from upstream #7496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions llvm/lib/MC/WinCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,9 @@ void WinCOFFWriter::executePostLayoutBinding(MCAssembler &Asm,

if (Mode != DwoOnly)
for (const MCSymbol &Symbol : Asm.symbols())
if (!Symbol.isTemporary())
// Define non-temporary or temporary static (private-linkage) symbols
if (!Symbol.isTemporary() ||
cast<MCSymbolCOFF>(Symbol).getClass() == COFF::IMAGE_SYM_CLASS_STATIC)
DefineSymbol(Symbol, Asm, Layout);
}

Expand Down Expand Up @@ -909,7 +911,7 @@ void WinCOFFWriter::recordRelocation(MCAssembler &Asm,
Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

// Turn relocations for temporary symbols into section relocations.
if (A.isTemporary()) {
if (A.isTemporary() && !SymbolMap[&A]) {
MCSection *TargetSection = &A.getSection();
assert(
SectionMap.contains(TargetSection) &&
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ class AArch64AsmPrinter : public AsmPrinter {
SetupMachineFunction(MF);

if (STI->isTargetCOFF()) {
bool Internal = MF.getFunction().hasInternalLinkage();
COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC
: COFF::IMAGE_SYM_CLASS_EXTERNAL;
bool Local = MF.getFunction().hasLocalLinkage();
COFF::SymbolStorageClass Scl =
Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL;
int Type =
COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;

Expand Down
42 changes: 27 additions & 15 deletions llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1993,23 +1993,32 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF);
bool HasWinCFI = false;
bool IsFunclet = false;
auto WinCFI = make_scope_exit([&]() { assert(HasWinCFI == MF.hasWinCFI()); });

if (MBB.end() != MBBI) {
DL = MBBI->getDebugLoc();
IsFunclet = isFuncletReturnInstr(*MBBI);
}

MachineBasicBlock::iterator EpilogStartI = MBB.end();

auto FinishingTouches = make_scope_exit([&]() {
InsertReturnAddressAuth(MF, MBB, NeedsWinCFI, &HasWinCFI);
if (needsShadowCallStackPrologueEpilogue(MF))
emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL);
if (EmitCFI)
emitCalleeSavedGPRRestores(MBB, MBB.getFirstTerminator());
if (HasWinCFI)
if (HasWinCFI) {
BuildMI(MBB, MBB.getFirstTerminator(), DL,
TII->get(AArch64::SEH_EpilogEnd))
.setMIFlag(MachineInstr::FrameDestroy);
if (!MF.hasWinCFI())
MF.setHasWinCFI(true);
}
if (NeedsWinCFI) {
assert(EpilogStartI != MBB.end());
if (!HasWinCFI)
MBB.erase(EpilogStartI);
}
});

int64_t NumBytes = IsFunclet ? getWinEHFuncletFrameSize(MF)
Expand Down Expand Up @@ -2074,7 +2083,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
// Adjust local stack
emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
StackOffset::getFixed(AFI->getLocalStackSize()), TII,
MachineInstr::FrameDestroy, false, NeedsWinCFI);
MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);

// SP has been already adjusted while restoring callee save regs.
// We've bailed-out the case with adjusting SP for arguments.
Expand Down Expand Up @@ -2126,16 +2135,17 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
NeedsWinCFI, &HasWinCFI);
}

if (MF.hasWinCFI()) {
// If the prologue didn't contain any SEH opcodes and didn't set the
// MF.hasWinCFI() flag, assume the epilogue won't either, and skip the
// EpilogStart - to avoid generating CFI for functions that don't need it.
// (And as we didn't generate any prologue at all, it would be asymmetrical
// to the epilogue.) By the end of the function, we assert that
// HasWinCFI is equal to MF.hasWinCFI(), to verify this assumption.
HasWinCFI = true;
if (NeedsWinCFI) {
// Note that there are cases where we insert SEH opcodes in the
// epilogue when we had no SEH opcodes in the prologue. For
// example, when there is no stack frame but there are stack
// arguments. Insert the SEH_EpilogStart and remove it later if it
// we didn't emit any SEH opcodes to avoid generating WinCFI for
// functions that don't need it.
BuildMI(MBB, LastPopI, DL, TII->get(AArch64::SEH_EpilogStart))
.setMIFlag(MachineInstr::FrameDestroy);
EpilogStartI = LastPopI;
--EpilogStartI;
}

if (hasFP(MF) && AFI->hasSwiftAsyncContext()) {
Expand Down Expand Up @@ -2289,11 +2299,11 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
emitFrameOffset(
MBB, LastPopI, DL, AArch64::SP, AArch64::FP,
StackOffset::getFixed(-AFI->getCalleeSaveBaseToFrameRecordOffset()),
TII, MachineInstr::FrameDestroy, false, NeedsWinCFI);
TII, MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);
} else if (NumBytes)
emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP,
StackOffset::getFixed(NumBytes), TII,
MachineInstr::FrameDestroy, false, NeedsWinCFI);
MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI);

// When we are about to restore the CSRs, the CFA register is SP again.
if (EmitCFI && hasFP(MF)) {
Expand Down Expand Up @@ -2750,7 +2760,8 @@ static void computeCalleeSaveRegisterPairs(
// Swift's async context is directly before FP, so allocate an extra
// 8 bytes for it.
if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
RPI.Reg2 == AArch64::FP)
((!IsWindows && RPI.Reg2 == AArch64::FP) ||
(IsWindows && RPI.Reg2 == AArch64::LR)))
ByteOffset += StackFillDir * 8;

assert(!(RPI.isScalable() && RPI.isPaired()) &&
Expand Down Expand Up @@ -2779,7 +2790,8 @@ static void computeCalleeSaveRegisterPairs(
// The FP, LR pair goes 8 bytes into our expanded 24-byte slot so that the
// Swift context can directly precede FP.
if (NeedsFrameRecord && AFI->hasSwiftAsyncContext() &&
RPI.Reg2 == AArch64::FP)
((!IsWindows && RPI.Reg2 == AArch64::FP) ||
(IsWindows && RPI.Reg2 == AArch64::LR)))
Offset += 8;
RPI.Offset = Offset / Scale;

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
return (Value >> 2) & 0x3fff;
case AArch64::fixup_aarch64_pcrel_branch26:
case AArch64::fixup_aarch64_pcrel_call26:
if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) {
// MSVC link.exe and lld do not support this relocation type
// with a non-zero offset
Ctx.reportError(Fixup.getLoc(),
"cannot perform a PC-relative fixup with a non-zero "
"symbol offset");
}
// Signed 28-bit immediate
if (SignedValue > 134217727 || SignedValue < -134217728)
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/CodeGen/AArch64/local-sym-storage-class.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; RUN: llc -mtriple aarch64-unknown-windows-msvc %s -o - | FileCheck %s

define internal void @internal() {
ret void
}

define private void @private() {
ret void
}

; Check that the internal and private linkage symbols have IMAGE_SYM_CLASS_STATIC (3).
; CHECK: .def internal;
; CHECK: .scl 3;
; CHECK: .def .Lprivate;
; CHECK: .scl 3;
32 changes: 32 additions & 0 deletions llvm/test/CodeGen/AArch64/swift-async-context-slot-offset-win.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; RUN: llc -mtriple aarch64-unknown-windows-msvc -filetype asm %s -o - | FileCheck %s

; Check that the slot offset of the async context (x22) doesn't
; conflict with that of another callee-saved register (x21 here) and
; saving it won't overwrite the saved value of the callee-saved
; register.
;
; CHECK: sub sp, sp, #64
; CHECK: str x19, [sp, #16]
; CHECK: str x21, [sp, #24]
; CHECK-NOT: stp x29, x30, [sp, #32]
; CHECK: stp x29, x30, [sp, #40]
; CHECK-NOT: str x22, [sp, #24]
; CHECK: str x22, [sp, #32]

declare ptr @llvm.swift.async.context.addr()
declare swiftcc i64 @foo(i64 %0, i64 %1)
declare swifttailcc void @tail(ptr swiftasync %0, ptr swiftself dereferenceable(8) %1, i64 %2)
define internal swifttailcc void @test(ptr swiftasync %0, ptr swiftself %1, i64 %2) {
entry:
%3 = load ptr, ptr %0, align 8
%4 = call ptr @llvm.swift.async.context.addr()
store ptr %3, ptr %4, align 8
%5 = call swiftcc i64 @foo(i64 %2, i64 %2)
%6 = call swiftcc i64 @foo(i64 %2, i64 %5)
%7 = call swiftcc i64 @foo(i64 %5, i64 %2)
%8 = call swiftcc i64 @foo(i64 %7, i64 %6)
%9 = call swiftcc i64 @foo(i64 %2, i64 %8)
%10 = call ptr @llvm.swift.async.context.addr()
musttail call swifttailcc void @tail(ptr swiftasync %10, ptr swiftself %1, i64 %2)
ret void
}
13 changes: 13 additions & 0 deletions llvm/test/CodeGen/AArch64/wincfi-seh-only-in-epilogue.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; RUN: llc -mtriple=aarch64-windows %s -o - | FileCheck %s

define hidden swifttailcc void @test(ptr noalias nocapture %0, ptr swiftasync %1, ptr %2, ptr noalias nocapture %3, ptr nocapture dereferenceable(8) %4, ptr %5, ptr %6, ptr %Act, ptr %Err, ptr %Res, ptr %Act.DistributedActor, ptr %Err.Error, ptr %Res.Decodable, ptr %Res.Encodable, ptr swiftself %7) #0 {
entry:
ret void
}

; Check that there is no .seh_endprologue but there is seh_startepilogue/seh_endepilogue.
; CHECK-NOT: .seh_endprologue
; CHECK: .seh_startepilogue
; CHECK: add sp, sp, #48
; CHECK: .seh_stackalloc 48
; CHECK: .seh_endepilogue
15 changes: 15 additions & 0 deletions llvm/test/CodeGen/X86/local-sym-storage-class.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; RUN: llc -mtriple x86_64-unknown-windows-msvc %s -o - | FileCheck %s

define internal void @internal() {
ret void
}

define private void @private() {
ret void
}

; Check that the internal and private linkage symbols have IMAGE_SYM_CLASS_STATIC (3).
; CHECK: .def internal;
; CHECK: .scl 3;
; CHECK: .def .Lprivate;
; CHECK: .scl 3;
75 changes: 75 additions & 0 deletions llvm/test/MC/AArch64/coff-relocations-branch26.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// RUN: llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj %s -o - | llvm-objdump -D -r - | FileCheck %s
// RUN: not llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR

.text
main:
nop
b .Ltarget
b .Lother_target

// A privte label target in the same section
.def .Ltarget
.scl 3
.type 32
.endef
.p2align 2
.Ltarget:
ret

// A privte label target in another section
.section "other"
nop
nop
nop
nop
nop
nop
nop
nop
.def .Lother_target
.scl 3
.type 32
.endef
.p2align 2
.Lother_target:
ret

// Check that both branches have a relocation with a zero offset.
//
// CHECK: 0000000000000000 <main>:
// CHECK: 0: d503201f nop
// CHECK: 4: 14000000 b 0x4 <main+0x4>
// CHECK: 0000000000000004: IMAGE_REL_ARM64_BRANCH26 .Ltarget
// CHECK: 8: 14000000 b 0x8 <main+0x8>
// CHECK: 0000000000000008: IMAGE_REL_ARM64_BRANCH26 .Lother_target
// CHECK: 000000000000000c <.Ltarget>:
// CHECK: c: d65f03c0 ret
// CHECK: 0000000000000000 <other>:
// CHECK: 0: d503201f nop
// CHECK: 4: d503201f nop
// CHECK: 8: d503201f nop
// CHECK: c: d503201f nop
// CHECK: 10: d503201f nop
// CHECK: 14: d503201f nop
// CHECK: 18: d503201f nop
// CHECK: 1c: d503201f nop
// CHECK: 0000000000000020 <.Lother_target>:
// CHECK: 20: d65f03c0 ret

.ifdef ERR
.section "err"
err:
nop
b .Lerr_target+4
// ERR: [[#@LINE-1]]:5: error: cannot perform a PC-relative fixup with a non-zero symbol offset

.def .Lerr_target
.scl 3
.type 32
.p2align 2
.endef
.Lerr_target:
nop
nop
ret
.endif