diff --git a/cl/_testdata/printf/in.go b/cl/_testdata/printf/in.go new file mode 100644 index 00000000..00b867e8 --- /dev/null +++ b/cl/_testdata/printf/in.go @@ -0,0 +1,12 @@ +package main + +import _ "unsafe" + +//go:linkname printf _printf +func printf(format *int8, __llgo_va_list ...any) + +var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0} + +func main() { + printf(&hello[0]) +} diff --git a/cl/_testdata/printf/out.ll b/cl/_testdata/printf/out.ll new file mode 100644 index 00000000..693d1261 --- /dev/null +++ b/cl/_testdata/printf/out.ll @@ -0,0 +1,32 @@ +; ModuleID = 'main' +source_filename = "main" + +@"init$guard" = global ptr null +@hello = global ptr null + +define void @init() { +_llgo_0: + %0 = load i1, ptr @"init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"init$guard", align 1 + store i8 72, ptr @hello, align 1 + store i8 101, ptr getelementptr inbounds (i8, ptr @hello, i64 1), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 2), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 3), align 1 + store i8 111, ptr getelementptr inbounds (i8, ptr @hello, i64 4), align 1 + store i8 10, ptr getelementptr inbounds (i8, ptr @hello, i64 5), align 1 + store i8 0, ptr getelementptr inbounds (i8, ptr @hello, i64 6), align 1 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +declare void @printf(ptr, ...) + +define void @main() { +_llgo_0: + ret void +} diff --git a/cl/compile.go b/cl/compile.go index eaf12345..c1934f5f 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -38,9 +38,8 @@ type context struct { prog llssa.Program pkg llssa.Package fn llssa.Function - fns map[*ssa.Function]llssa.Function - glbs map[*ssa.Global]llssa.Global bvals map[ssa.Value]llssa.Expr // block values + inits []func() } func (p *context) compileType(pkg llssa.Package, member *ssa.Type) { @@ -48,41 +47,28 @@ func (p *context) compileType(pkg llssa.Package, member *ssa.Type) { } // Global variable. -func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) llssa.Global { - if g, ok := p.glbs[gbl]; ok { - return g - } +func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) { g := pkg.NewVar(gbl.Name(), gbl.Type()) g.Init(p.prog.Null(g.Type)) - p.glbs[gbl] = g - return g } -func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) llssa.Function { - if fn, ok := p.fns[f]; ok { - return fn - } - fn := p.doCompileFunc(pkg, f) - p.fns[f] = fn - return fn -} - -func (p *context) doCompileFunc(pkg llssa.Package, f *ssa.Function) (fn llssa.Function) { - fn = pkg.NewFunc(f.Name(), f.Signature) - p.fn = fn - defer func() { - p.fn = nil - }() - nblk := len(f.Blocks) - if nblk == 0 { // external function - return - } - fn.MakeBlocks(nblk) - b := fn.NewBuilder() - for _, block := range f.Blocks { - p.compileBlock(b, block) - } - return +func (p *context) compileFunc(pkg llssa.Package, f *ssa.Function) { + fn := pkg.NewFunc(f.Name(), f.Signature) + p.inits = append(p.inits, func() { + p.fn = fn + defer func() { + p.fn = nil + }() + nblk := len(f.Blocks) + if nblk == 0 { // external function + return + } + fn.MakeBlocks(nblk) + b := fn.NewBuilder() + for _, block := range f.Blocks { + p.compileBlock(b, block) + } + }) } func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock) llssa.BasicBlock { @@ -101,10 +87,12 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l } switch v := iv.(type) { case *ssa.Call: - call := v.Call - fn := p.compileValue(b, call.Value) - args := p.compileValues(b, call.Args) - ret = b.Call(fn, args...) + if false { + call := v.Call + fn := p.compileValue(b, call.Value) + args := p.compileValues(b, call.Args) + ret = b.Call(fn, args...) + } case *ssa.BinOp: x := p.compileValue(b, v.X) y := p.compileValue(b, v.Y) @@ -112,6 +100,13 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l case *ssa.UnOp: x := p.compileValue(b, v.X) ret = b.UnOp(v.Op, x) + case *ssa.IndexAddr: + x := p.compileValue(b, v.X) + idx := p.compileValue(b, v.Index) + ret = b.IndexAddr(x, idx) + case *ssa.Alloc: + t := v.Type() + ret = b.Alloc(p.prog.Type(t), v.Heap) default: panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv)) } @@ -168,13 +163,14 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr { } } case *ssa.Function: - fn := p.compileFunc(p.pkg, v) + fn := p.pkg.FuncOf(v.Name()) return fn.Expr case *ssa.Global: - g := p.compileGlobal(p.pkg, v) + g := p.pkg.VarOf(v.Name()) return g.Expr case *ssa.Const: - return b.Const(v.Value, v.Type()) + t := v.Type() + return b.Const(v.Value, p.prog.Type(t)) } panic(fmt.Sprintf("compileValue: unknown value - %T\n", v)) } @@ -215,8 +211,6 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.P ctx := &context{ prog: prog, pkg: ret, - fns: make(map[*ssa.Function]llssa.Function), - glbs: make(map[*ssa.Global]llssa.Global), } for _, m := range members { member := m.val @@ -233,6 +227,9 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, conf *Config) (ret llssa.P ctx.compileGlobal(ret, member) } } + for _, ini := range ctx.inits { + ini() + } return } diff --git a/cl/compile_test.go b/cl/compile_test.go index d4810cd8..303e0cbe 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -34,7 +34,12 @@ import ( ) func TestFromTestdata(t *testing.T) { - testFromDir(t, "", "./_testdata") + testFromDir(t, "printf", "./_testdata") +} + +func init() { + llssa.Initialize(llssa.InitAll) + llssa.SetDebug(llssa.DbgFlagAll) } func testFromDir(t *testing.T, sel, relDir string) { diff --git a/go.mod b/go.mod index a32e2249..176d938d 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/aykevl/go-wasm v0.0.1 github.com/goplus/gop v1.2.6 - github.com/goplus/llvm v0.7.1-0.20240418160956-6233231cbcc9 + github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47 github.com/qiniu/x v1.13.10 golang.org/x/tools v0.19.0 ) diff --git a/go.sum b/go.sum index c8c84464..4543999d 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/goplus/gop v1.2.6 h1:kog3c5Js+8EopqmI4+CwueXsqibnBwYVt5q5N7juRVY= github.com/goplus/gop v1.2.6/go.mod h1:uREWbR1MrFaviZ4Mbx4ZCcAYDoqzO0iv1Qo6Np0Xx4E= github.com/goplus/llvm v0.7.1-0.20240418160956-6233231cbcc9 h1:E/NBN5tDh6COcJmygdBb9RAJhE4uIHfT51VBlP3tglU= github.com/goplus/llvm v0.7.1-0.20240418160956-6233231cbcc9/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4= +github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47 h1:B3nWTLOQh4+Yqt6NryE/cVQdo/+NLiT8AtD4YaeKScg= +github.com/goplus/llvm v0.7.1-0.20240420180312-6230a4ea7a47/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4= github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE= github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c= github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE= diff --git a/ssa/decl.go b/ssa/decl.go index 878789f8..1be102ad 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -130,7 +130,7 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) { } params = make([]Type, n) for i := 0; i < n; i++ { - params[i] = prog.llvmType(in.At(i).Type()) + params[i] = prog.Type(in.At(i).Type()) } } return diff --git a/ssa/expr.go b/ssa/expr.go index 67609313..8c6ce9ae 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -17,9 +17,12 @@ package ssa import ( + "bytes" + "fmt" "go/constant" "go/token" "go/types" + "log" "github.com/goplus/llvm" ) @@ -57,16 +60,15 @@ func (p Program) BoolVal(v bool) Expr { return Expr{ret, t} } -func (p Program) IntVal(v int) Expr { - t := p.Int() - ret := llvm.ConstInt(t.ll, uint64(v), false) +func (p Program) IntVal(v uint64, t Type) Expr { + ret := llvm.ConstInt(t.ll, v, false) return Expr{ret, t} } func (p Program) Val(v interface{}) Expr { switch v := v.(type) { case int: - return p.IntVal(v) + return p.IntVal(uint64(v), p.Int()) case bool: return p.BoolVal(v) case float64: @@ -77,15 +79,16 @@ func (p Program) Val(v interface{}) Expr { panic("todo") } -func (b Builder) Const(v constant.Value, t types.Type) Expr { - switch t := t.(type) { +func (b Builder) Const(v constant.Value, typ Type) Expr { + switch t := typ.t.(type) { case *types.Basic: - switch t.Kind() { - case types.Bool: + kind := t.Kind() + switch { + case kind == types.Bool: return b.prog.BoolVal(constant.BoolVal(v)) - case types.Int: - if v, exact := constant.Int64Val(v); exact { - return b.prog.IntVal(int(v)) + case kind >= types.Int && kind <= types.Uintptr: + if v, exact := constant.Uint64Val(v); exact { + return b.prog.IntVal(v, typ) } } } @@ -191,6 +194,9 @@ func isPredOp(op token.Token) bool { // AND OR XOR SHL SHR AND_NOT & | ^ << >> &^ // EQL NEQ LSS LEQ GTR GEQ == != < <= < >= func (b Builder) BinOp(op token.Token, x, y Expr) Expr { + if debugInstr { + log.Printf("BinOp %d, %v, %v\n", op, x.impl, y.impl) + } switch { case isMathOp(op): // op: + - * / % kind := x.kind @@ -243,25 +249,109 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr { case token.MUL: return b.Load(x) } + if debugInstr { + log.Printf("UnOp %v, %v\n", op, x.impl) + } panic("todo") } // Load returns the value at the pointer ptr. func (b Builder) Load(ptr Expr) Expr { - elem := ptr.t.(*types.Pointer).Elem() - telem := b.prog.llvmType(elem) + if debugInstr { + log.Printf("Load @%v\n", ptr.impl.Name()) + } + telem := b.prog.Elem(ptr.Type) return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem} } // Store stores val at the pointer ptr. func (b Builder) Store(ptr, val Expr) Builder { + if debugInstr { + log.Printf("Store @%v, %v\n", ptr.impl.Name(), val.impl) + } b.impl.CreateStore(val.impl, ptr.impl) return b } +// The IndexAddr instruction yields the address of the element at +// index `idx` of collection `x`. `idx` is an integer expression. +// +// The elements of maps and strings are not addressable; use Lookup (map), +// Index (string), or MapUpdate instead. +// +// Dynamically, this instruction panics if `x` evaluates to a nil *array +// pointer. +// +// Example printed form: +// +// t2 = &t0[t1] +func (b Builder) IndexAddr(x, idx Expr) Expr { + if debugInstr { + log.Printf("IndexAddr %v, %v\n", x.impl, idx.impl) + } + prog := b.prog + telem := prog.Index(x.Type) + pt := prog.Pointer(telem) + indices := []llvm.Value{idx.impl} + return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, x.impl, indices), pt} +} + +// The Alloc instruction reserves space for a variable of the given type, +// zero-initializes it, and yields its address. +// +// If heap is false, Alloc zero-initializes the same local variable in +// the call frame and returns its address; in this case the Alloc must +// be present in Function.Locals. We call this a "local" alloc. +// +// If heap is true, Alloc allocates a new zero-initialized variable +// each time the instruction is executed. We call this a "new" alloc. +// +// When Alloc is applied to a channel, map or slice type, it returns +// the address of an uninitialized (nil) reference of that kind; store +// the result of MakeSlice, MakeMap or MakeChan in that location to +// instantiate these types. +// +// Example printed form: +// +// t0 = local int +// t1 = new int +func (b Builder) Alloc(t Type, heap bool) (ret Expr) { + if debugInstr { + log.Printf("Alloc %v, %v\n", t.ll, heap) + } + telem := b.prog.Elem(t) + if heap { + ret.impl = llvm.CreateAlloca(b.impl, telem.ll) + } else { + panic("todo") + } + // TODO: zero-initialize + ret.Type = t + return +} + // ----------------------------------------------------------------------------- +// The Call instruction represents a function or method call. +// +// The Call instruction yields the function result if there is exactly +// one. Otherwise it returns a tuple, the components of which are +// accessed via Extract. +// +// Example printed form: +// +// t2 = println(t0, t1) +// t4 = t3() +// t7 = invoke t5.Println(...t6) func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { + if debugInstr { + var b bytes.Buffer + fmt.Fprint(&b, "Call @", fn.impl.Name()) + for _, arg := range args { + fmt.Fprint(&b, ", ", arg.impl) + } + log.Println(b.String()) + } switch t := fn.t.(type) { case *types.Signature: ret.Type = b.prog.retType(t) diff --git a/ssa/package.go b/ssa/package.go index 592df3a3..ce3969e0 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -19,11 +19,29 @@ package ssa import ( "go/constant" "go/types" + "log" "github.com/goplus/llvm" "golang.org/x/tools/go/types/typeutil" ) +type dbgFlags = int + +const ( + DbgFlagInstruction dbgFlags = 1 << iota + + DbgFlagAll = DbgFlagInstruction +) + +var ( + debugInstr bool +) + +// SetDebug sets debug flags. +func SetDebug(dbgFlags dbgFlags) { + debugInstr = (dbgFlags & DbgFlagInstruction) != 0 +} + // ----------------------------------------------------------------------------- // InitFlags is a set of flags for initializing the LLVM library. @@ -112,7 +130,9 @@ func NewProgram(target *Target) Program { func (p Program) NewPackage(name, pkgPath string) Package { mod := p.ctx.NewModule(pkgPath) mod.Finalize() - return &aPackage{mod, p} + fns := make(map[string]Function) + gbls := make(map[string]Global) + return &aPackage{mod, fns, gbls, p} } // Void returns void type. @@ -126,7 +146,7 @@ func (p Program) Void() Type { // Bool returns bool type. func (p Program) Bool() Type { if p.boolTy == nil { - p.boolTy = p.llvmType(types.Typ[types.Bool]) + p.boolTy = p.Type(types.Typ[types.Bool]) } return p.boolTy } @@ -134,7 +154,7 @@ func (p Program) Bool() Type { // Int returns int type. func (p Program) Int() Type { if p.intTy == nil { - p.intTy = p.llvmType(types.Typ[types.Int]) + p.intTy = p.Type(types.Typ[types.Int]) } return p.intTy } @@ -142,7 +162,7 @@ func (p Program) Int() Type { // Float64 returns float64 type. func (p Program) Float64() Type { if p.f64Ty == nil { - p.f64Ty = p.llvmType(types.Typ[types.Float64]) + p.f64Ty = p.Type(types.Typ[types.Float64]) } return p.f64Ty } @@ -159,6 +179,8 @@ func (p Program) Float64() Type { // and unspecified other things too. type aPackage struct { mod llvm.Module + fns map[string]Function + vars map[string]Global prog Program } @@ -170,18 +192,40 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst { // NewVar creates a new global variable. func (p Package) NewVar(name string, typ types.Type) Global { - t := p.prog.llvmType(typ) + if debugInstr { + log.Println("==> NewVar", name, typ) + } + t := p.prog.Type(typ) gbl := llvm.AddGlobal(p.mod, t.ll, name) - return &aGlobal{Expr{gbl, t}} + ret := &aGlobal{Expr{gbl, t}} + p.vars[name] = ret + return ret } // NewFunc creates a new function. func (p Package) NewFunc(name string, sig *types.Signature) Function { + if debugInstr { + log.Println("==> NewFunc", name) + } t := p.prog.llvmSignature(sig) fn := llvm.AddFunction(p.mod, name, t.ll) - return newFunction(fn, t, p.prog) + ret := newFunction(fn, t, p.prog) + p.fns[name] = ret + return ret } +// FuncOf returns a function by name. +func (p Package) FuncOf(name string) Function { + return p.fns[name] +} + +// VarOf returns a global variable by name. +func (p Package) VarOf(name string) Global { + return p.vars[name] +} + +// ----------------------------------------------------------------------------- + // String returns a string representation of the package. func (p Package) String() string { return p.mod.String() diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 3fe9f1cf..1d7c83c2 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -25,6 +25,7 @@ import ( func init() { Initialize(InitAll) + SetDebug(DbgFlagAll) } func assertPkg(t *testing.T, p Package, expected string) { @@ -55,7 +56,7 @@ func TestConst(t *testing.T) { rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Bool])) sig := types.NewSignatureType(nil, nil, nil, nil, rets, false) b := pkg.NewFunc("fn", sig).MakeBody(1) - b.Return(b.Const(constant.MakeBool(true), types.Typ[types.Bool])) + b.Return(b.Const(constant.MakeBool(true), prog.Bool())) assertPkg(t, pkg, `; ModuleID = 'foo/bar' source_filename = "foo/bar" diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 63f8bedd..a5e2f1f2 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -17,6 +17,10 @@ package ssa import ( + "bytes" + "fmt" + "log" + "github.com/goplus/llvm" ) @@ -57,12 +61,26 @@ func (b Builder) SetBlock(blk BasicBlock) Builder { if b.fn != blk.fn { panic("mismatched function") } + if debugInstr { + log.Printf("Block _llgo_%v:\n", blk.idx) + } b.impl.SetInsertPointAtEnd(blk.impl) return b } // Return emits a return instruction. func (b Builder) Return(results ...Expr) { + if debugInstr { + var b bytes.Buffer + fmt.Fprint(&b, "Return ") + for i, arg := range results { + if i > 0 { + fmt.Fprint(&b, ", ") + } + fmt.Fprint(&b, arg.impl) + } + log.Println(b.String()) + } switch n := len(results); n { case 0: b.impl.CreateRetVoid() @@ -78,6 +96,9 @@ func (b Builder) Jump(jmpb BasicBlock) { if b.fn != jmpb.fn { panic("mismatched function") } + if debugInstr { + log.Printf("Jump _llgo_%v\n", jmpb.idx) + } b.impl.CreateBr(jmpb.impl) } @@ -86,6 +107,9 @@ func (b Builder) If(cond Expr, thenb, elseb BasicBlock) { if b.fn != thenb.fn || b.fn != elseb.fn { panic("mismatched function") } + if debugInstr { + log.Printf("If %v, _llgo_%v, _llgo_%v\n", cond.impl, thenb.idx, elseb.idx) + } b.impl.CreateCondBr(cond.impl, thenb.impl, elseb.impl) } diff --git a/ssa/type.go b/ssa/type.go index ddf955b6..c6cc8c28 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -57,6 +57,21 @@ func HasVArg(t *types.Tuple, n int) bool { return n > 0 && IsVArg(t.At(n-1)) } +func indexType(t types.Type) types.Type { + switch t := t.(type) { + case *types.Slice: + return t.Elem() + case *types.Pointer: + switch t := t.Elem().(type) { + case *types.Array: + return t.Elem() + } + case *types.Array: + return t.Elem() + } + panic("index: type doesn't support index - " + t.String()) +} + // ----------------------------------------------------------------------------- type aType struct { @@ -67,7 +82,20 @@ type aType struct { type Type = *aType -func (p Program) llvmType(typ types.Type) Type { +func (p Program) Pointer(typ Type) Type { + return p.Type(types.NewPointer(typ.t)) +} + +func (p Program) Elem(typ Type) Type { + elem := typ.t.(*types.Pointer).Elem() + return p.Type(elem) +} + +func (p Program) Index(typ Type) Type { + return p.Type(indexType(typ.t)) +} + +func (p Program) Type(typ types.Type) Type { if v := p.typs.At(typ); v != nil { return v.(Type) } @@ -185,7 +213,7 @@ func (p Program) toLLVMType(typ types.Type) Type { return &aType{p.tyVoidPtr(), typ, vkInvalid} } case *types.Pointer: - elem := p.llvmType(t.Elem()) + elem := p.Type(t.Elem()) return &aType{llvm.PointerType(elem.ll, 0), typ, vkInvalid} case *types.Slice: case *types.Map: @@ -196,7 +224,7 @@ func (p Program) toLLVMType(typ types.Type) Type { case *types.Signature: return p.toLLVMFunc(t) case *types.Array: - elem := p.llvmType(t.Elem()) + elem := p.Type(t.Elem()) return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid} case *types.Chan: } @@ -221,7 +249,7 @@ func (p Program) toLLVMFields(typ *types.Struct) (fields []llvm.Type) { if n > 0 { fields = make([]llvm.Type, n) for i := 0; i < n; i++ { - fields[i] = p.llvmType(typ.Field(i).Type()).ll + fields[i] = p.Type(typ.Field(i).Type()).ll } } return @@ -235,7 +263,7 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) { if n > 0 { ret = make([]llvm.Type, n) for i := 0; i < n; i++ { - ret[i] = p.llvmType(t.At(i).Type()).ll + ret[i] = p.Type(t.At(i).Type()).ll } } return @@ -255,7 +283,7 @@ func (p Program) toLLVMFunc(sig *types.Signature) Type { case 0: ret = p.tyVoid() case 1: - ret = p.llvmType(out.At(0).Type()).ll + ret = p.Type(out.At(0).Type()).ll default: ret = p.toLLVMTuple(out) } @@ -269,7 +297,7 @@ func (p Program) retType(sig *types.Signature) Type { case 0: return p.Void() case 1: - return p.llvmType(out.At(0).Type()) + return p.Type(out.At(0).Type()) default: return &aType{p.toLLVMTuple(out), out, vkTuple} } diff --git a/x/loader/loader.go b/x/loader/loader.go deleted file mode 100644 index 15240a9c..00000000 --- a/x/loader/loader.go +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package loader - -/* -import ( - "go/ast" - "go/token" - "go/types" - - "github.com/goplus/llgo/build" - "golang.org/x/tools/go/ssa" -) - -type Package struct { - SSA *ssa.Package - EmbedGlobals map[string][]*EmbedFile -} - -type EmbedFile struct { - /* - Name string - Size uint64 - Hash string // hash of the file (as a hex string) - NeedsData bool // true if this file is embedded as a byte slice - Data []byte // contents of this file (only if NeedsData is set) -*/ -/* -} - -type Context struct { - *ssa.Program -} - -func (ctx *Context) Load(pkg build.Package) (ret Package, err error) { - return -} - -// BuildPackage builds an SSA program with IR for a single package. -// -// It populates pkg by type-checking the specified file ASTs. All -// dependencies are loaded using the importer specified by tc, which -// typically loads compiler export data; SSA code cannot be built for -// those packages. BuildPackage then constructs an ssa.Program with all -// dependency packages created, and builds and returns the SSA package -// corresponding to pkg. -// -// The caller must have set pkg.Path() to the import path. -// -// The operation fails if there were any type-checking or import errors. -// -// See ../example_test.go for an example. -func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) { - if fset == nil { - panic("no token.FileSet") - } - if pkg.Path() == "" { - panic("package has no import path") - } - - info := &types.Info{ - Types: make(map[ast.Expr]types.TypeAndValue), - Defs: make(map[*ast.Ident]types.Object), - Uses: make(map[*ast.Ident]types.Object), - Implicits: make(map[ast.Node]types.Object), - Scopes: make(map[ast.Node]*types.Scope), - Selections: make(map[*ast.SelectorExpr]*types.Selection), - } - typeparams.InitInstanceInfo(info) - versions.InitFileVersions(info) - if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil { - return nil, nil, err - } - - prog := ssa.NewProgram(fset, mode) - - // Create SSA packages for all imports. - // Order is not significant. - created := make(map[*types.Package]bool) - var createAll func(pkgs []*types.Package) - createAll = func(pkgs []*types.Package) { - for _, p := range pkgs { - if !created[p] { - created[p] = true - prog.CreatePackage(p, nil, nil, true) - createAll(p.Imports()) - } - } - } - createAll(pkg.Imports()) - - // TODO(adonovan): we could replace createAll with just: - // - // // Create SSA packages for all imports. - // for _, p := range pkg.Imports() { - // prog.CreatePackage(p, nil, nil, true) - // } - // - // (with minor changes to changes to ../builder_test.go as - // shown in CL 511715 PS 10.) But this would strictly violate - // the letter of the doc comment above, which says "all - // dependencies created". - // - // Tim makes the good point with some extra work we could - // remove the need for any CreatePackage calls except the - // ones with syntax (i.e. primary packages). Of course - // You wouldn't have ssa.Packages and Members for as - // many things but no-one really uses that anyway. - // I wish I had done this from the outset. - - // Create and build the primary package. - ssapkg := prog.CreatePackage(pkg, files, info, false) - ssapkg.Build() - return ssapkg, info, nil -} -*/ diff --git a/x/parser/parser.go b/x/parser/parser.go deleted file mode 100644 index 32c815cd..00000000 --- a/x/parser/parser.go +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package parser - -/* -import ( - "go/ast" - "go/parser" - "go/token" - - "github.com/goplus/llgo/build" -) - -// A Mode value is a set of flags (or 0). -// They control the amount of source code parsed and other optional -// parser functionality. -type Mode = parser.Mode - -const ( - PackageClauseOnly = parser.PackageClauseOnly // stop parsing after package clause - ImportsOnly = parser.ImportsOnly // stop parsing after import declarations - ParseComments = parser.ParseComments // parse comments and add them to AST - Trace = parser.Trace // print a trace of parsed productions - DeclarationErrors = parser.DeclarationErrors // report declaration errors - SpuriousErrors = parser.SpuriousErrors // same as AllErrors, for backward-compatibility - SkipObjectResolution = parser.SkipObjectResolution // don't resolve identifiers to objects - see ParseFile - AllErrors = parser.AllErrors // report all errors (not just the first 10 on different lines) -) - -// A Package node represents a set of source files -// collectively building a Go package. -type Package struct { - *ast.Package -} - -func Parse(fset *token.FileSet, pkg build.Package, mode Mode) (_ Package, first error) { - ret := map[string]*ast.Package{} - for _, file := range pkg.GoFiles { - f, err := parser.ParseFile(fset, file, nil, mode) - if err != nil { - if first == nil { - first = err - } - continue - } - ret[file] = f - } -} -*/