diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -633,6 +633,10 @@ return Scale == 1; } + /// If the target has a standard location for the stack protector cookie, + /// returns the address of that location. Otherwise, returns nullptr. + Value *getIRStackGuard(IRBuilderBase &IRB) const override; + private: /// RISCVCCAssignFn - This target-specific function extends the default /// CCValAssign with additional information used to lower RISC-V calling diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -14221,6 +14221,25 @@ return true; } +static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) { + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + Function *ThreadPointerFunc = + Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); + return IRB.CreatePointerCast( + IRB.CreateConstGEP1_32(IRB.getInt8Ty(), + IRB.CreateCall(ThreadPointerFunc), Offset), + IRB.getInt8PtrTy()->getPointerTo(0)); +} + +Value *RISCVTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const { + // Fuchsia provides a fixed TLS slot for the stack cookie. + // defines ZX_TLS_STACK_GUARD_OFFSET with this value. + if (Subtarget.isTargetFuchsia()) + return useTpOffset(IRB, -0x10); + + return TargetLowering::getIRStackGuard(IRB); +} + #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -176,6 +176,8 @@ const LegalizerInfo *getLegalizerInfo() const override; const RegisterBankInfo *getRegBankInfo() const override; + bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); } + bool useConstantPoolForLargeInts() const; // Maximum cost used for building integers, integers will be put into constant diff --git a/llvm/test/CodeGen/RISCV/stack-protector-target.ll b/llvm/test/CodeGen/RISCV/stack-protector-target.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/stack-protector-target.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +;; Test target-specific stack cookie location. +; +; RUN: llc -mtriple=riscv64-fuchsia < %s | FileCheck --check-prefix=FUCHSIA-RISCV64 %s + +define void @func() sspreq { +; FUCHSIA-RISCV64-LABEL: func: +; FUCHSIA-RISCV64: # %bb.0: +; FUCHSIA-RISCV64-NEXT: addi sp, sp, -32 +; FUCHSIA-RISCV64-NEXT: .cfi_def_cfa_offset 32 +; FUCHSIA-RISCV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; FUCHSIA-RISCV64-NEXT: .cfi_offset ra, -8 +; FUCHSIA-RISCV64-NEXT: ld a0, -16(tp) +; FUCHSIA-RISCV64-NEXT: sd a0, 16(sp) +; FUCHSIA-RISCV64-NEXT: addi a0, sp, 12 +; FUCHSIA-RISCV64-NEXT: call capture@plt +; FUCHSIA-RISCV64-NEXT: ld a0, -16(tp) +; FUCHSIA-RISCV64-NEXT: ld a1, 16(sp) +; FUCHSIA-RISCV64-NEXT: bne a0, a1, .LBB0_2 +; FUCHSIA-RISCV64-NEXT: # %bb.1: # %SP_return +; FUCHSIA-RISCV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; FUCHSIA-RISCV64-NEXT: addi sp, sp, 32 +; FUCHSIA-RISCV64-NEXT: ret +; FUCHSIA-RISCV64-NEXT: .LBB0_2: # %CallStackCheckFailBlk +; FUCHSIA-RISCV64-NEXT: call __stack_chk_fail@plt + %1 = alloca i32, align 4 + call void @capture(ptr nonnull %1) + ret void +} + +declare void @capture(ptr)