19
cl/_testdata/method/in.go
Normal file
19
cl/_testdata/method/in.go
Normal 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))
|
||||||
|
}
|
||||||
44
cl/_testdata/method/out.ll
Normal file
44
cl/_testdata/method/out.ll
Normal 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
|
||||||
|
}
|
||||||
@@ -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),
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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{}
|
||||||
}
|
}
|
||||||
|
|||||||
29
ssa/type.go
29
ssa/type.go
@@ -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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user