Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ brew link --overwrite llvm@19 lld@19 libffi
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libcjson-dev libsqlite3-dev libuv1-dev
sudo apt-get install -y llvm-19-dev clang-19 libclang-19-dev lld-19 libunwind-19-dev libc++-19-dev pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libsqlite3-dev libuv1-dev
sudo apt-get install -y python3.12-dev # optional
#curl https://raw.githubusercontent.com/xgo-dev/llgo/refs/heads/main/install.sh | bash
./install.sh
Expand Down
36 changes: 32 additions & 4 deletions chore/litgen/rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var (
globalRefRE = regexp.MustCompile(`@"([^"]+)"|@([A-Za-z0-9$._-]+)`)
checkLineRE = regexp.MustCompile(`^\s*//\s*CHECK(?:-[A-Z]+)?:`)
debugMetaRE = regexp.MustCompile(`, ![A-Za-z0-9_.-]+ ![0-9]+`)
closureEnvRE = regexp.MustCompile(`(\s)(?:nest|swiftself)(\s)`)
numericNameRE = regexp.MustCompile(`^\d+$`)
)

Expand Down Expand Up @@ -439,9 +440,37 @@ func generalizeIRLine(line, modulePath string) string {

func scrubIRLine(line string) string {
line = debugMetaRE.ReplaceAllString(line, "")
line = generalizeClosureEnvAttrs(line)
return strings.TrimRight(line, " \t")
}

func generalizeClosureEnvAttrs(line string) string {
var b strings.Builder
start := 0
inQuote := false
for i := 0; i < len(line); i++ {
if line[i] != '"' || isEscapedQuote(line, i) {
continue
}
if !inQuote {
b.WriteString(closureEnvRE.ReplaceAllString(line[start:i], `${1}{{(nest|swiftself)}}${2}`))
b.WriteByte('"')
start = i + 1
inQuote = true
continue
}
b.WriteString(line[start : i+1])
start = i + 1
inQuote = false
}
if inQuote {
b.WriteString(line[start:])
} else {
b.WriteString(closureEnvRE.ReplaceAllString(line[start:], `${1}{{(nest|swiftself)}}${2}`))
}
return b.String()
}

func generalizeModulePath(line, modulePath string) string {
if modulePath == "" {
return line
Expand Down Expand Up @@ -499,10 +528,9 @@ func collectRefs(line string) []string {
}

func shouldSkipFunctionCheck(symbol string) bool {
base := strings.TrimPrefix(symbol, "__llgo_stub.")
return strings.HasSuffix(base, "/runtime/internal/runtime.memequal32") ||
strings.HasSuffix(base, "/runtime/internal/runtime.memequalptr") ||
strings.HasSuffix(base, "/runtime/internal/runtime.strequal")
return strings.HasSuffix(symbol, "/runtime/internal/runtime.memequal32") ||
strings.HasSuffix(symbol, "/runtime/internal/runtime.memequalptr") ||
strings.HasSuffix(symbol, "/runtime/internal/runtime.strequal")
}

func trimPkgPrefix(symbol, pkgPath string) (string, bool) {
Expand Down
42 changes: 30 additions & 12 deletions chore/litgen/rewrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
)

func TestRewriteSource_InsertsMainClosureAndStub(t *testing.T) {
func TestRewriteSource_InsertsMainAndClosure(t *testing.T) {
const src = `// LITTEST
package main

Expand All @@ -25,11 +25,6 @@ _llgo_0:
ret void
}

define linkonce void @"__llgo_stub.example.com/p.main$1"(ptr %0) {
_llgo_0:
tail call void @"example.com/p.main$1"()
ret void
}
`
got, err := rewriteSource(src, "in.go", "example.com/p", "example.com", ir)
if err != nil {
Expand All @@ -51,12 +46,6 @@ _llgo_0:
if strings.Index(got, closureCheck) > strings.Index(got, closureStmt) {
t.Fatalf("closure checks should appear before func literal:\n%s", got)
}
if !strings.Contains(got, `// CHECK-LABEL: define linkonce void @"__llgo_stub.{{.*}}/p.main$1"(ptr %0){{.*}} {`) {
t.Fatalf("stub checks missing:\n%s", got)
}
if strings.Index(got, `// CHECK-LABEL: define linkonce void @"__llgo_stub.{{.*}}/p.main$1"(ptr %0){{.*}} {`) < strings.Index(got, "func main()") {
t.Fatalf("stub checks should be appended after source:\n%s", got)
}
}

func TestRewriteSource_AddsInitAndCheckEmptyAndSkipsHelpers(t *testing.T) {
Expand Down Expand Up @@ -233,6 +222,35 @@ func TestGeneralizeDefineLine_WildcardsAttrsBeforeBrace(t *testing.T) {
}
}

func TestGeneralizeClosureEnvAttrs(t *testing.T) {
tests := []struct {
line string
want string
}{
{
`define void @"example.com/nest.swiftself"(ptr swiftself %env) {`,
`define void @"example.com/nest.swiftself"(ptr {{(nest|swiftself)}} %env) {`,
},
{
` call void %fn(ptr nest %env, ptr %arg)`,
` call void %fn(ptr {{(nest|swiftself)}} %env, ptr %arg)`,
},
{
`@0 = private constant [14 x i8] c"nest swiftself"`,
`@0 = private constant [14 x i8] c"nest swiftself"`,
},
{
`@nest = global ptr @swiftself`,
`@nest = global ptr @swiftself`,
},
}
for _, test := range tests {
if got := generalizeClosureEnvAttrs(test.line); got != test.want {
t.Errorf("generalizeClosureEnvAttrs(%q) = %q, want %q", test.line, got, test.want)
}
}
}

func TestGeneralizeModulePath_ReplacesOnlyQuotedSegments(t *testing.T) {
line := ` %0 = getelementptr inbounds %"go/example.Type", ptr @"go/example.fn"`
got := generalizeModulePath(line, "go")
Expand Down
4 changes: 2 additions & 2 deletions chore/pclnpost/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ func main() {
fmt.Fprintln(os.Stderr, "pclnpost:", err)
os.Exit(1)
}
fmt.Printf("%s: entry=%d stub=%d kept=%d inlineCopies=%d noSymbol=%d -> ftab=%d buckets=%d\n",
st.Format, st.EntryRecords, st.StubRecords, st.Kept, st.InlineCopies, st.NoSymbol, st.FtabEntries, st.Buckets)
fmt.Printf("%s: entry=%d kept=%d inlineCopies=%d noSymbol=%d -> ftab=%d buckets=%d\n",
st.Format, st.EntryRecords, st.Kept, st.InlineCopies, st.NoSymbol, st.FtabEntries, st.Buckets)
}
6 changes: 0 additions & 6 deletions cl/_testdata/foo/foo.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,3 @@ func (g *Game) Load() {
// CHECK-NEXT: _llgo_2: ; preds = %_llgo_1, %_llgo_0
// CHECK-NEXT: ret void
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }
2 changes: 1 addition & 1 deletion cl/_testdata/llgointrinsics/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func UseCTrampoline() uintptr {
// CHECK-NEXT: %0 = call ptr @"{{.*}}.AllocZ"(i64 8)
// CHECK-NEXT: %1 = call ptr @"{{.*}}.AllocU"(i64 8)
// CHECK: ret i64 ptrtoint (ptr @"{{.*}}.UseClosure$1" to i64)
// CHECK-LABEL: define void @"{{.*}}.UseClosure$1"(ptr %0){{.*}} {
// CHECK-LABEL: define void @"{{.*}}.UseClosure$1"(ptr {{(nest|swiftself)}} %0){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK: %4 = add i64 %3, 1
// CHECK: ret void
Expand Down
42 changes: 0 additions & 42 deletions cl/_testdata/print/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -1389,45 +1389,3 @@ func prinxor(n int64) {
func stringStructOf(sp *string) *stringStruct {
return (*stringStruct)(unsafe.Pointer(sp))
}

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f32equal"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f32equal"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.f64equal"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.f64equal"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal8"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal8"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal16"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal16"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.memequal64"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.memequal64"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.c128equal"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.c128equal"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }

// CHECK-LABEL: define linkonce i1 @"__llgo_stub.{{.*}}/runtime/internal/runtime.c64equal"(ptr %0, ptr %1, ptr %2){{.*}} {
// CHECK-NEXT: _llgo_0:
// CHECK-NEXT: %3 = tail call i1 @"{{.*}}/runtime/internal/runtime.c64equal"(ptr %1, ptr %2)
// CHECK-NEXT: ret i1 %3
// CHECK-NEXT: }
Loading
Loading