Merge pull request #51 from xushiwei/q

cl: _testdata/method
This commit is contained in:
xushiwei
2024-04-25 21:47:36 +08:00
committed by GitHub
7 changed files with 115 additions and 15 deletions

19
cl/_testdata/method/in.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import _ "unsafe"
type T int
func (a T) Add(b T) T {
return a + b
}
//go:linkname printf printf
func printf(format *int8, __llgo_va_list ...any)
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func main() {
a := T(1)
printf(&format[0], a.Add(2))
}

View File

@@ -0,0 +1,44 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@main.format = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i64 @"(main.T).Add"(i64 %0, i64 %1) {
_llgo_0:
%2 = add i64 %0, %1
ret i64 %2
}
declare void @printf(ptr, ...)
define void @main() {
_llgo_0:
call void @main.init()
%0 = call i64 @"(main.T).Add"(i64 1, i64 2)
call void (ptr, ...) @printf(ptr @main.format, i64 %0)
ret void
}

View File

@@ -92,6 +92,7 @@ type context struct {
pkg llssa.Package pkg llssa.Package
fn llssa.Function fn llssa.Function
fset *token.FileSet fset *token.FileSet
goProg *ssa.Program
goTyps *types.Package goTyps *types.Package
goPkg *ssa.Package goPkg *ssa.Package
link map[string]string // pkgPath.nameInPkg => linkname link map[string]string // pkgPath.nameInPkg => linkname
@@ -101,8 +102,20 @@ type context struct {
inits []func() inits []func()
} }
func (p *context) compileType(pkg llssa.Package, member *ssa.Type) { func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
panic("todo") tn := t.Object().(*types.TypeName)
typ := tn.Type()
name := fullName(tn.Pkg(), tn.Name())
if debugInstr {
log.Println("==> NewType", name, typ)
}
prog := p.goProg
mthds := prog.MethodSets.MethodSet(typ)
for i, n := 0, mthds.Len(); i < n; i++ {
mthd := mthds.At(i)
ssaMthd := prog.MethodValue(mthd)
p.compileFunc(pkg, ssaMthd)
}
} }
// Global variable. // Global variable.
@@ -118,11 +131,13 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) { func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) {
name := p.funcName(f.Pkg.Pkg, f) name := p.funcName(f.Pkg.Pkg, f)
/* TODO(xsw): confirm this is not needed more
if name == "unsafe.init" { if name == "unsafe.init" {
return return
} }
*/
if debugInstr { if debugInstr {
log.Println("==> NewFunc", name) log.Println("==> NewFunc", name, f.Signature)
} }
fn := pkg.NewFunc(name, f.Signature) fn := pkg.NewFunc(name, f.Signature)
p.inits = append(p.inits, func() { p.inits = append(p.inits, func() {
@@ -378,6 +393,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
return iPos < jPos return iPos < jPos
}) })
pkgProg := pkg.Prog
pkgTypes := pkg.Pkg pkgTypes := pkg.Pkg
pkgName, pkgPath := pkgTypes.Name(), pathOf(pkgTypes) pkgName, pkgPath := pkgTypes.Name(), pathOf(pkgTypes)
ret = prog.NewPackage(pkgName, pkgPath) ret = prog.NewPackage(pkgName, pkgPath)
@@ -385,7 +401,8 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
ctx := &context{ ctx := &context{
prog: prog, prog: prog,
pkg: ret, pkg: ret,
fset: pkg.Prog.Fset, fset: pkgProg.Fset,
goProg: pkgProg,
goTyps: pkgTypes, goTyps: pkgTypes,
goPkg: pkg, goPkg: pkg,
link: make(map[string]string), link: make(map[string]string),

View File

@@ -116,7 +116,13 @@ func fullName(pkg *types.Package, name string) string {
return pathOf(pkg) + "." + name return pathOf(pkg) + "." + name
} }
// func: pkg.name
// method: (pkg.T).name
func funcName(pkg *types.Package, fn *ssa.Function) string { func funcName(pkg *types.Package, fn *ssa.Function) string {
sig := fn.Signature
if recv := sig.Recv(); recv != nil {
return "(" + recv.Type().String() + ")." + fn.Name()
}
ret := fullName(pkg, fn.Name()) ret := fullName(pkg, fn.Name())
if ret == "main.main" { if ret == "main.main" {
ret = "main" ret = "main"

View File

@@ -258,7 +258,7 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr {
// Load returns the value at the pointer ptr. // Load returns the value at the pointer ptr.
func (b Builder) Load(ptr Expr) Expr { func (b Builder) Load(ptr Expr) Expr {
if debugInstr { if debugInstr {
log.Printf("Load %v\n", ptr.impl.Name()) log.Printf("Load %v\n", ptr.impl)
} }
telem := b.prog.Elem(ptr.Type) telem := b.prog.Elem(ptr.Type)
return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem} return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem}
@@ -267,7 +267,7 @@ func (b Builder) Load(ptr Expr) Expr {
// Store stores val at the pointer ptr. // Store stores val at the pointer ptr.
func (b Builder) Store(ptr, val Expr) Builder { func (b Builder) Store(ptr, val Expr) Builder {
if debugInstr { if debugInstr {
log.Printf("Store %v, %v\n", ptr.impl.Name(), val.impl) log.Printf("Store %v, %v\n", ptr.impl, val.impl)
} }
b.impl.CreateStore(val.impl, ptr.impl) b.impl.CreateStore(val.impl, ptr.impl)
return b return b
@@ -346,7 +346,7 @@ func (b Builder) Alloc(t Type, heap bool) (ret Expr) {
func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
if debugInstr { if debugInstr {
var b bytes.Buffer var b bytes.Buffer
fmt.Fprint(&b, "Call @", fn.impl.Name()) fmt.Fprint(&b, "Call ", fn.impl.Name())
for _, arg := range args { for _, arg := range args {
fmt.Fprint(&b, ", ", arg.impl) fmt.Fprint(&b, ", ", arg.impl)
} }

View File

@@ -187,6 +187,7 @@ type aPackage struct {
type Package = *aPackage type Package = *aPackage
// NewConst creates a new named constant.
func (p Package) NewConst(name string, val constant.Value) NamedConst { func (p Package) NewConst(name string, val constant.Value) NamedConst {
return &aNamedConst{} return &aNamedConst{}
} }

View File

@@ -17,8 +17,8 @@
package ssa package ssa
import ( import (
"fmt"
"go/types" "go/types"
"log"
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
@@ -108,8 +108,21 @@ func (p Program) llvmSignature(sig *types.Signature) Type {
if v := p.typs.At(sig); v != nil { if v := p.typs.At(sig); v != nil {
return v.(Type) return v.(Type)
} }
sigOrg := sig
if recv := sig.Recv(); recv != nil {
// convert method to func
tParams := sig.Params()
nParams := tParams.Len()
params := make([]*types.Var, nParams+1)
params[0] = recv
for i := 0; i < nParams; i++ {
params[i+1] = tParams.At(i)
}
sig = types.NewSignatureType(
nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
}
ret := p.toLLVMFunc(sig) ret := p.toLLVMFunc(sig)
p.typs.Set(sig, ret) p.typs.Set(sigOrg, ret)
return ret return ret
} }
@@ -228,8 +241,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid} return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
case *types.Chan: case *types.Chan:
} }
log.Println("toLLVMType: todo -", typ) panic(fmt.Sprintf("toLLVMType: todo - %T\n", typ))
panic("todo")
} }
func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type { func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
@@ -304,12 +316,13 @@ func (p Program) retType(sig *types.Signature) Type {
} }
func (p Program) toLLVMNamed(typ *types.Named) Type { func (p Program) toLLVMNamed(typ *types.Named) Type {
name := typ.Obj().Name() switch t := typ.Underlying().(type) {
switch typ := typ.Underlying().(type) {
case *types.Struct: case *types.Struct:
return &aType{p.toLLVMNamedStruct(name, typ), typ, vkInvalid} name := typ.Obj().Name()
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
default:
return p.Type(t)
} }
panic("todo")
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------