Skip to content

cmd/compile: compiler stores a stack pointer into a global object #61730

@wildoranges

Description

@wildoranges

What version of Go are you using (go version)?

$ go version
go version go1.20.5 linux/amd64

Does this issue reproduce with the latest release?

Yes, I can reproduce in go1.20.7 linux/amd64

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="auto"
GOARCH="amd64"
GOBIN=""
GOCACHE="xxx/.cache/go-build"
GOENV="xxx/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="xxx/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="xxx/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="xxx/golang/go1.20.5"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="xxx/golang/go1.20.5/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.5"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2743047067=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I use go1.20.5 to compile the following code:

package main

func use(...interface{}) {
   
}

func main() {
    testCases := [...][][]int{
        {{42}},
        {{1, 2}},
        {{3, 4, 5}},
        {{}},
        {{1, 2}, {3, 4, 5}, {}, {7}},
    }
    for _, testCase := range testCases {
        use(testCase)
    }
}

In the generated SSA and assembly code, I notice that the Go compiler generates some instructions that store a stack pointer(point to the stack-allocated array) into a global slice header.

Just like the assembly code below, the MOV instruction at 0x4585bf stores a stack pointer into a global object:

  0x458589		48c744240800000000       MOVQ $0x0, 0x8(SP)	
  0x458592		48c74424082a000000	MOVQ $0x2a, 0x8(SP)	
	testCases := [...][][]int{
  0x45859b		48c705c28e060001000000	MOVQ $0x1, 0x68ec2(IP)			
  0x4585a6		48c705bf8e060001000000	MOVQ $0x1, 0x68ebf(IP)			
  0x4585b1		833d988d090000		CMPL $0x0, runtime.writeBarrier(SB)	
  0x4585b8		750e			JNE 0x4585c8				
  0x4585ba		488d442408		LEAQ 0x8(SP), AX			
  0x4585bf		4889059a8e0600		MOVQ AX, 0x68e9a(IP)			
  0x4585c6		eb11			JMP 0x4585d9				
  0x4585c8		488d3d918e0600		LEAQ 0x68e91(IP), DI			
  0x4585cf		488d442408		LEAQ 0x8(SP), AX			
  0x4585d4		e8e7cfffff		CALL runtime.gcWriteBarrier(SB)

I have read the comments in slicelit, but I didn't find any operations that can generate such stores. As far as I know, pointers to stack objects cannot be stored in global objects. So is this a compiler bug? Or the Go compiler does this on purpose to achieve some optimization I don't know yet?

note: this is originally posted on golang-nuts

Thanks

What did you expect to see?

The stack pointer is not stored into any global object.

What did you see instead?

The stack pointer is stored into a global object.

Metadata

Metadata

Assignees

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

In Progress

Relationships

None yet

Development

No branches or pull requests

Issue actions