Merge pull request #1304 from MeteorsLiu/impl-stacksave

feat: implement `llgo.stackSave`
This commit is contained in:
xushiwei
2025-11-13 07:48:01 +08:00
committed by GitHub
8 changed files with 115 additions and 2 deletions

View File

@@ -0,0 +1,22 @@
//go:build amd64
package main
import (
"unsafe"
_ "unsafe"
)
//go:linkname getsp llgo.stackSave
func getsp() unsafe.Pointer
//go:linkname asmFull llgo.asm
func asmFull(instruction string, regs map[string]any) uintptr { return 0 }
func main() {
sp := asmFull("movq %rsp, {}", nil)
if sp != uintptr(getsp()) {
panic("invalid stack pointer")
}
}

View File

@@ -0,0 +1,22 @@
//go:build arm64
package main
import (
"unsafe"
_ "unsafe"
)
//go:linkname getsp llgo.stackSave
func getsp() unsafe.Pointer
//go:linkname asmFull llgo.asm
func asmFull(instruction string, regs map[string]any) uintptr { return 0 }
func main() {
sp := asmFull("mov {}, sp", nil)
if sp != uintptr(getsp()) {
panic("invalid stack pointer")
}
}

View File

@@ -0,0 +1,14 @@
package main
import (
"unsafe"
_ "unsafe"
)
//go:linkname getsp llgo.stackSave
func getsp() unsafe.Pointer
func main() {
sp := getsp()
println(sp)
}

View File

@@ -0,0 +1,34 @@
; ModuleID = 'github.com/goplus/llgo/cl/_testrt/stacksave'
source_filename = "github.com/goplus/llgo/cl/_testrt/stacksave"
@"github.com/goplus/llgo/cl/_testrt/stacksave.init$guard" = global i1 false, align 1
define void @"github.com/goplus/llgo/cl/_testrt/stacksave.init"() {
_llgo_0:
%0 = load i1, ptr @"github.com/goplus/llgo/cl/_testrt/stacksave.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"github.com/goplus/llgo/cl/_testrt/stacksave.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define void @"github.com/goplus/llgo/cl/_testrt/stacksave.main"() {
_llgo_0:
%0 = call ptr @llvm.stacksave()
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintPointer"(ptr %0)
call void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8 10)
ret void
}
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare ptr @llvm.stacksave() #0
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintPointer"(ptr)
declare void @"github.com/goplus/llgo/runtime/internal/runtime.PrintByte"(i8)
attributes #0 = { nocallback nofree nosync nounwind willreturn }

View File

@@ -503,7 +503,8 @@ const (
llgoCgoCheckPointer = llgoCgoBase + 0x6
llgoCgoCgocall = llgoCgoBase + 0x7
llgoAsm = llgoInstrBase + 0x40
llgoAsm = llgoInstrBase + 0x40
llgoStackSave = llgoInstrBase + 0x41
llgoAtomicOpLast = llgoAtomicOpBase + int(llssa.OpUMin)
)

View File

@@ -425,7 +425,8 @@ var llgoInstrs = map[string]int{
"_cgoCheckPointer": llgoCgoCheckPointer,
"_cgo_runtime_cgocall": llgoCgoCgocall,
"asm": llgoAsm,
"asm": llgoAsm,
"stackSave": llgoStackSave,
}
// funcOf returns a function by name and set ftype = goFunc, cFunc, etc.
@@ -601,6 +602,8 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
ret = p.sigsetjmp(b, args)
case llgoSiglongjmp:
p.siglongjmp(b, args)
case llgoStackSave:
ret = b.StackSave()
case llgoSigjmpbuf: // func sigjmpbuf()
ret = b.AllocaSigjmpBuf()
case llgoDeferData: // func deferData() *Defer

View File

@@ -91,6 +91,16 @@ func (p Program) tySiglongjmp() *types.Signature {
return p.sigljmpTy
}
// func() unsafe.Pointer
func (p Program) tyStacksave() *types.Signature {
if p.stackSaveTy == nil {
paramPtr := types.NewParam(token.NoPos, nil, "", p.VoidPtr().raw.Type)
params := types.NewTuple(paramPtr)
p.stackSaveTy = types.NewSignatureType(nil, nil, nil, nil, params, false)
}
return p.stackSaveTy
}
func (b Builder) AllocaSigjmpBuf() Expr {
prog := b.Prog
n := unsafe.Sizeof(sigjmpbuf{})
@@ -98,6 +108,12 @@ func (b Builder) AllocaSigjmpBuf() Expr {
return b.Alloca(size)
}
// declare ptr @llvm.stacksave.p0()
func (b Builder) StackSave() Expr {
fn := b.Pkg.cFunc("llvm.stacksave", b.Prog.tyStacksave())
return b.InlineCall(fn)
}
func (b Builder) Sigsetjmp(jb, savemask Expr) Expr {
if b.Prog.target.GOARCH == "wasm" {
return b.Setjmp(jb)

View File

@@ -195,6 +195,7 @@ type aProgram struct {
mallocTy *types.Signature
freeTy *types.Signature
memsetInlineTy *types.Signature
stackSaveTy *types.Signature
createKeyTy *types.Signature
getSpecTy *types.Signature