How does stack overflow handles in gollvm

110 views
Skip to first unread message

Kavindu Gimhan Zoysa

unread,
Jun 23, 2021, 10:32:39 PM6/23/21
to golang-nuts
Hi all,

package main

func main() {
foo()
}

func foo() {
a := 5
_ = a
foo()
}

I have generated the below llvm ir using the command `./bin/llvm-goc -S test.go -dump-ir`. I expected there are some llvm intrinsics that have been used to handle stack overflow. But it is not there. How does gollvm handle stackoverflow?

define void @main.main(i8* nest %nest.0) #0 !dbg !14 {
entry:
  call void @main.foo(i8* nest undef), !dbg !15
  ret void
}

define void @main.foo(i8* nest %nest.1) #0 !dbg !16 {
entry:
  %a = alloca i64, align 8
  %0 = bitcast i64* %a to i8*
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %0)
  store i64 5, i64* %a, align 8
  call void @llvm.dbg.declare(metadata i64* %a, metadata !17, metadata !DIExpression()), !dbg !20
  %a.ld.0 = load i64, i64* %a, align 8, !dbg !21
  call void @main.foo(i8* nest undef), !dbg !22
  %1 = bitcast i64* %a to i8*
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %1)
  ret void
}

Kurtis Rader

unread,
Jun 23, 2021, 10:47:33 PM6/23/21
to Kavindu Gimhan Zoysa, golang-nuts
This might be an XY Problem, or your question simply needs more context. Your sample program is an example of infinite recursion. How that is detected is platform specific. It might be done via a special signal. Or it might be done by a syscall to grow the stack returning an error. So my question is, why are you asking how infinite recursion is handled?

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0bbb1347-5ceb-4ed2-9622-cb695d29bc6dn%40googlegroups.com.


--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Kavindu Gimhan Zoysa

unread,
Jun 23, 2021, 11:10:53 PM6/23/21
to golang-nuts
Hi Kurtis,

Thank you for your input. 

I am searching how do languages handle stack overflow. Languages like rust, handle this by catching SIGSEGV. In golang, as I found, it was handled by increasing the stack[1], [2] (Sorry if my terms are wrong). I have generated object dump(objdump -d) for go source code (just a function call) I can see that at the beginning of every function call it checks for the stack overflow and try to increase the stack(see //go:nosplit section of [2]). I am lloking how does gollvm handle this. 

00000000004871a0 <main.foo>:
  4871a0: 64 48 8b 0c 25 f8 ff mov    %fs:0xfffffffffffffff8,%rcx
  4871a7: ff ff 
  4871a9: 48 8d 44 24 f8        lea    -0x8(%rsp),%rax
  4871ae: 48 3b 41 10                  cmp    0x10(%rcx),%rax
  4871b2: 0f 86 e1 00 00 00    jbe    487299 <main.foo+0xf9>
                                                ........
  487299: e8 62 80 fc ff                callq  44f300 <runtime.morestack_noctxt>
  48729e: e9 fd fe ff ff                jmpq   4871a0 <main.foo>

Than McIntosh

unread,
Jun 24, 2021, 9:36:00 AM6/24/21
to Kavindu Gimhan Zoysa, golang-nuts
Hello,

If you go into your LLVM IR dump and look at the place where the function is defined, you'll see a reference to an attribute set, e.g.


  define void @main.foo(i8* nest %nest.1) #0 !dbg !16 {

Here "#0" refers to this attribute set (appearing later in the dump):

attributes #0 = { "disable-tail-calls"="true" "frame-pointer"="none" "null-pointer-is-valid"="true" "split-stack" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }

One of these attributes is "split-stack". When this attribute is set, the LLVM back end will emit a stack check in the prolog with a call to expand the stack if needed.

You can find this code at

https://github.com/llvm/llvm-project/blob/25bb61649085c0a6e66630bbffe7faa54cd67829/llvm/lib/CodeGen/PrologEpilogInserter.cpp#L1128

Hope this helps.

Thanks, Than

Reply all
Reply to author
Forward
0 new messages