diff --git a/cl/compile.go b/cl/compile.go index 00f63ee9..9db16bcb 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -560,8 +560,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue cv := v.Call.Value if mthd := v.Call.Method; mthd != nil { o := p.compileValue(b, cv) + fn := b.Imethod(o, v.Call.Method) args := p.compileValues(b, v.Call.Args, fnNormal) - ret = b.Icall(o, v.Call.Method, args...) + b.Call(fn, args...) break } kind := p.funcKind(cv) diff --git a/internal/runtime/z_closure.go b/internal/runtime/z_closure.go deleted file mode 100644 index d47818b3..00000000 --- a/internal/runtime/z_closure.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2024 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 runtime - -/* -import ( - "unsafe" -) - -// Closure represents a closure. -type Closure struct { - f unsafe.Pointer - data unsafe.Pointer // means no context if data is nil -} - -// NewClosure creates a closure. -func NewClosure(f, data unsafe.Pointer) Closure { - return Closure{f, data} -} - -// ClosureF returns the function of a closure. -func ClosureF(c Closure) unsafe.Pointer { - return c.f -} - -// ClosureData returns the data of a closure. -func ClosureData(c Closure) unsafe.Pointer { - return c.data -} -*/ diff --git a/ssa/expr.go b/ssa/expr.go index 436d40fa..c013da55 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -900,15 +900,6 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) { return b.Call(fn, args...) } -// The Icall instruction represents a interface method call. -// -// Example printed form: -// -// t7 = invoke t5.Println(...t6) -func (b Builder) Icall(o Expr, method *types.Func, args ...Expr) (ret Expr) { - panic("todo") -} - // The Call instruction represents a function call. // // The Call instruction yields the function result if there is exactly @@ -1079,11 +1070,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { typ = prog.Float64() case vkSlice: fn = "PrintSlice" - case vkPtr, vkFuncPtr, vkFuncDecl: - fn = "PrintPointer" - typ = prog.VoidPtr() case vkClosure: arg = b.Field(arg, 0) + fallthrough + case vkPtr, vkFuncPtr, vkFuncDecl: fn = "PrintPointer" typ = prog.VoidPtr() case vkString: diff --git a/ssa/interface.go b/ssa/interface.go index 52b4669b..a318a78d 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -226,6 +226,31 @@ func (b Builder) unsafeInterface(rawIntf *types.Interface, t Expr, data llvm.Val return b.unsafeIface(itab.impl, data) } +func iMethodOf(rawIntf *types.Interface, method *types.Func) int { + name := method.Name() + n := rawIntf.NumMethods() + for i := 0; i < n; i++ { + m := rawIntf.Method(i) + if m.Name() == name { + // TODO(xsw): check signature + return i + } + } + return -1 +} + +// Imethod returns closure of an interface method. +func (b Builder) Imethod(intf Expr, method *types.Func) Expr { + prog := b.Prog + rawIntf := intf.raw.Type.Underlying().(*types.Interface) + i := iMethodOf(rawIntf, method) + impl := intf.impl + itab := Expr{b.faceItab(impl), prog.VoidPtrPtr()} + pfn := b.Advance(itab, prog.IntVal(uint64(i+3), prog.Int())) + tclosure := prog.Type(method.Type(), InGo) + return b.aggregateValue(tclosure, b.Load(pfn).impl, b.faceData(impl)) +} + // ----------------------------------------------------------------------------- // MakeInterface constructs an instance of an interface type from a @@ -427,6 +452,10 @@ func (b Builder) faceData(x llvm.Value) llvm.Value { return llvm.CreateExtractValue(b.impl, x, 1) } +func (b Builder) faceItab(x llvm.Value) llvm.Value { + return llvm.CreateExtractValue(b.impl, x, 0) +} + func (b Builder) faceAbiType(x Expr) Expr { if x.kind == vkIface { panic("todo") diff --git a/ssa/package.go b/ssa/package.go index c7347a7f..dd562f4b 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -132,6 +132,7 @@ type aProgram struct { anyTy Type voidTy Type voidPtr Type + voidPPtr Type boolTy Type cstrTy Type cintTy Type @@ -371,6 +372,13 @@ func (p Program) VoidPtr() Type { return p.voidPtr } +func (p Program) VoidPtrPtr() Type { + if p.voidPPtr == nil { + p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer])) + } + return p.voidPPtr +} + // Bool returns bool type. func (p Program) Bool() Type { if p.boolTy == nil { diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index 9bf505b6..aa578b5d 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -66,27 +66,6 @@ func (p Program) FuncDecl(sig *types.Signature, bg Background) Type { return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl} } -/* -// cvtCxFunc converts a C extended function type into raw type. -func cvtCxFunc(sig *types.Signature, recv *types.Var) *types.Signature { - if sig.Variadic() { - // convert printf-like function type - tParams := sig.Params() - n := tParams.Len() - params := make([]*types.Var, n) - n-- - for i := 0; i < n; i++ { - params[i] = tParams.At(i) - } - params[n] = VArg() - sig = types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), true) - panic("todo") - } - sig = FuncAddCtx(recv, sig) - return sig -} -*/ - // Closure creates a closture type for a function. func (p Program) Closure(fn Type) Type { sig := fn.raw.Type.(*types.Signature)