Merge pull request #238 from xushiwei/q

llgo/ssa: Imethod; PrintIface; call intf.method
This commit is contained in:
xushiwei
2024-05-27 11:54:21 +08:00
committed by GitHub
18 changed files with 562 additions and 170 deletions

21
cl/_testgo/errors/in.go Normal file
View File

@@ -0,0 +1,21 @@
package main
// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
func main() {
err := New("an error")
println(err, err.Error())
}

213
cl/_testgo/errors/out.ll Normal file
View File

@@ -0,0 +1,213 @@
; ModuleID = 'main'
source_filename = "main"
%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr }
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%main.errorString = type { %"github.com/goplus/llgo/internal/runtime.String" }
%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1 }
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
%"github.com/goplus/llgo/internal/abi.Imethod" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr }
@"main.init$guard" = global ptr null
@"*main.errorString" = global ptr null
@"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU" = linkonce global ptr null
@__llgo_argc = global ptr null
@__llgo_argv = global ptr null
@0 = private unnamed_addr constant [9 x i8] c"an error\00", align 1
@1 = private unnamed_addr constant [2 x i8] c"s\00", align 1
@2 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@3 = private unnamed_addr constant [5 x i8] c"main\00", align 1
@4 = private unnamed_addr constant [5 x i8] c"main\00", align 1
@5 = private unnamed_addr constant [17 x i8] c"main.errorString\00", align 1
@6 = private unnamed_addr constant [6 x i8] c"Error\00", align 1
@"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to" = linkonce global ptr null
@7 = private unnamed_addr constant [5 x i8] c"main\00", align 1
define %"github.com/goplus/llgo/internal/runtime.iface" @main.New(%"github.com/goplus/llgo/internal/runtime.String" %0) {
_llgo_0:
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16)
%2 = getelementptr inbounds %main.errorString, ptr %1, i32 0, i32 0
store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8
%3 = load ptr, ptr @"*main.errorString", align 8
%4 = load ptr, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8
%5 = call ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr %4, ptr %3)
%6 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i32 0, i32 0
store ptr %5, ptr %7, align 8
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i32 0, i32 1
store ptr %1, ptr %8, align 8
%9 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8
ret %"github.com/goplus/llgo/internal/runtime.iface" %9
}
define %"github.com/goplus/llgo/internal/runtime.String" @"(*main.errorString).Error"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds %main.errorString, ptr %0, i32 0, i32 0
%2 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8
ret %"github.com/goplus/llgo/internal/runtime.String" %2
}
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
call void @"main.init$abi"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i32 @main(i32 %0, ptr %1) {
_llgo_0:
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0
store ptr @0, ptr %3, align 8
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1
store i64 8, ptr %4, align 4
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8
%6 = call %"github.com/goplus/llgo/internal/runtime.iface" @main.New(%"github.com/goplus/llgo/internal/runtime.String" %5)
%7 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %6, 0
%8 = getelementptr ptr, ptr %7, i64 3
%9 = load ptr, ptr %8, align 8
%10 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %6, 1
%11 = alloca { ptr, ptr }, align 8
%12 = getelementptr inbounds { ptr, ptr }, ptr %11, i32 0, i32 0
store ptr %9, ptr %12, align 8
%13 = getelementptr inbounds { ptr, ptr }, ptr %11, i32 0, i32 1
store ptr %10, ptr %13, align 8
%14 = load { ptr, ptr }, ptr %11, align 8
%15 = extractvalue { ptr, ptr } %14, 1
%16 = extractvalue { ptr, ptr } %14, 0
%17 = call %"github.com/goplus/llgo/internal/runtime.String" %16(ptr %15)
call void @"github.com/goplus/llgo/internal/runtime.PrintIface"(%"github.com/goplus/llgo/internal/runtime.iface" %6)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32)
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %17)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
ret i32 0
}
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr, ptr)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare void @"github.com/goplus/llgo/internal/runtime.PrintIface"(%"github.com/goplus/llgo/internal/runtime.iface")
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
define void @"main.init$abi"() {
_llgo_0:
%0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0
store ptr @1, ptr %1, align 8
%2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1
store i64 1, ptr %2, align 4
%3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8
%4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24)
%5 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 0
store ptr @2, ptr %6, align 8
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1
store i64 0, ptr %7, align 4
%8 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %5, align 8
%9 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %3, ptr %4, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %8, i1 false)
%10 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 0
store ptr @3, ptr %11, align 8
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 1
store i64 4, ptr %12, align 4
%13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %10, align 8
%14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 56)
%15 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %14, i64 0
store %"github.com/goplus/llgo/internal/abi.StructField" %9, ptr %15, align 8
%16 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 0
store ptr %14, ptr %17, align 8
%18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 1
store i64 1, ptr %18, align 4
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 2
store i64 1, ptr %19, align 4
%20 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, align 8
%21 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %13, i64 16, %"github.com/goplus/llgo/internal/runtime.Slice" %20)
%22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0
store ptr @4, ptr %23, align 8
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1
store i64 4, ptr %24, align 4
%25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8
%26 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0
store ptr @5, ptr %27, align 8
%28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1
store i64 16, ptr %28, align 4
%29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8
%30 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %25, %"github.com/goplus/llgo/internal/runtime.String" %29, ptr %21, { ptr, i64, i64 } zeroinitializer)
%31 = call ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr %30)
store ptr %31, ptr @"*main.errorString", align 8
%32 = load ptr, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8
%33 = icmp eq ptr %32, null
br i1 %33, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%34 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 0
store ptr @6, ptr %35, align 8
%36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 1
store i64 5, ptr %36, align 4
%37 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %34, align 8
%38 = load ptr, ptr @"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to", align 8
%39 = alloca %"github.com/goplus/llgo/internal/abi.Imethod", align 8
%40 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, i32 0, i32 0
store %"github.com/goplus/llgo/internal/runtime.String" %37, ptr %40, align 8
%41 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, i32 0, i32 1
store ptr %38, ptr %41, align 8
%42 = load %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, align 8
%43 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24)
%44 = getelementptr %"github.com/goplus/llgo/internal/abi.Imethod", ptr %43, i64 0
store %"github.com/goplus/llgo/internal/abi.Imethod" %42, ptr %44, align 8
%45 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8
%46 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 0
store ptr %43, ptr %46, align 8
%47 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 1
store i64 1, ptr %47, align 4
%48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 2
store i64 1, ptr %48, align 4
%49 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, align 8
%50 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 0
store ptr @7, ptr %51, align 8
%52 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 1
store i64 4, ptr %52, align 4
%53 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %50, align 8
%54 = call ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String" %53, %"github.com/goplus/llgo/internal/runtime.Slice" %49)
store ptr %54, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice")
declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1)
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64)
declare ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", ptr, %"github.com/goplus/llgo/internal/runtime.Slice")
declare ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr)
declare ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.Slice")

View File

@@ -20,7 +20,7 @@ source_filename = "main"
@3 = private unnamed_addr constant [2 x i8] c"F\00", align 1 @3 = private unnamed_addr constant [2 x i8] c"F\00", align 1
@4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@5 = private unnamed_addr constant [5 x i8] c"main\00", align 1 @5 = private unnamed_addr constant [5 x i8] c"main\00", align 1
@6 = private unnamed_addr constant [5 x i8] c"main\00", align 1 @6 = private unnamed_addr constant [39 x i8] c"github.com/goplus/llgo/cl/internal/foo\00", align 1
@7 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/internal/foo.Foo\00", align 1 @7 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/internal/foo.Foo\00", align 1
@8 = private unnamed_addr constant [3 x i8] c"pb\00", align 1 @8 = private unnamed_addr constant [3 x i8] c"pb\00", align 1
@9 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @9 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
@@ -257,7 +257,7 @@ _llgo_1: ; preds = %_llgo_0
%36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0 %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0
store ptr @6, ptr %36, align 8 store ptr @6, ptr %36, align 8
%37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1 %37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1
store i64 4, ptr %37, align 4 store i64 38, ptr %37, align 4
%38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8 %38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8
%39 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %39 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %39, i32 0, i32 0 %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %39, i32 0, i32 0

View File

@@ -115,7 +115,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0 _llgo_1: ; preds = %_llgo_0
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3) %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3)
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Pointer"(ptr %2) %3 = call ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr %2)
store ptr %3, ptr @"*_llgo_int8", align 8 store ptr %3, ptr @"*_llgo_int8", align 8
br label %_llgo_2 br label %_llgo_2
@@ -123,4 +123,4 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void ret void
} }
declare ptr @"github.com/goplus/llgo/internal/runtime.Pointer"(ptr) declare ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr)

View File

@@ -558,6 +558,13 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
switch v := iv.(type) { switch v := iv.(type) {
case *ssa.Call: case *ssa.Call:
cv := v.Call.Value 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.Call(fn, args...)
break
}
kind := p.funcKind(cv) kind := p.funcKind(cv)
if kind == fnIgnore { if kind == fnIgnore {
return return

View File

@@ -28,6 +28,10 @@ func testCompile(t *testing.T, src, expected string) {
cltest.TestCompileEx(t, src, "foo.go", expected) cltest.TestCompileEx(t, src, "foo.go", expected)
} }
func TestFromTestgo(t *testing.T) {
cltest.FromDir(t, "", "./_testgo", false)
}
func TestFromTestpy(t *testing.T) { func TestFromTestpy(t *testing.T) {
cltest.FromDir(t, "", "./_testpy", false) cltest.FromDir(t, "", "./_testpy", false)
} }

Binary file not shown.

Binary file not shown.

View File

@@ -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
}
*/

View File

@@ -43,6 +43,8 @@ type (
Itab = itab Itab = itab
) )
type Imethod = abi.Imethod
type Method = abi.Method
type FuncType = abi.FuncType type FuncType = abi.FuncType
type InterfaceType = abi.InterfaceType type InterfaceType = abi.InterfaceType
@@ -54,14 +56,105 @@ func ToEface(i Iface) Eface {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const ( const (
typeHdrSize = unsafe.Sizeof(abi.Type{}) typeHdrSize = unsafe.Sizeof(abi.Type{})
funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{}) arrayTypeHdrSize = unsafe.Sizeof(abi.ArrayType{})
uncommonTypeHdrSize = unsafe.Sizeof(abi.UncommonType{}) chanTypeHdrSize = unsafe.Sizeof(abi.ChanType{})
methodSize = unsafe.Sizeof(abi.Method{}) funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{})
pointerSize = unsafe.Sizeof(uintptr(0)) interfaceTypeHdrSize = unsafe.Sizeof(abi.InterfaceType{})
itabHdrSize = unsafe.Sizeof(itab{}) - pointerSize mapTypeHdrSize = unsafe.Sizeof(abi.MapType{})
ptrTypeHdrSize = unsafe.Sizeof(abi.PtrType{})
sliceTypeHdrSize = unsafe.Sizeof(abi.SliceType{})
structTypeHdrSize = unsafe.Sizeof(abi.StructType{})
uncommonTypeHdrSize = unsafe.Sizeof(abi.UncommonType{})
methodSize = unsafe.Sizeof(abi.Method{})
pointerSize = unsafe.Sizeof(uintptr(0))
itabHdrSize = unsafe.Sizeof(itab{}) - pointerSize
) )
var hdrSizes = [...]uintptr{
arrayTypeHdrSize,
chanTypeHdrSize,
funcTypeHdrSize,
interfaceTypeHdrSize,
mapTypeHdrSize,
ptrTypeHdrSize,
sliceTypeHdrSize,
typeHdrSize,
structTypeHdrSize,
}
func hdrSizeOf(kind abi.Kind) uintptr {
if kind >= abi.Array && kind <= abi.Struct {
return hdrSizes[kind-abi.Array]
}
return typeHdrSize
}
// Named returns a named type.
func Named(pkgPath, name string, underlying *Type, methods []abi.Method) *Type {
tflag := underlying.TFlag
if tflag&abi.TFlagUncommon != 0 {
panic("runtime: underlying type is already named")
}
kind := underlying.Kind()
n := len(methods)
if kind == abi.Interface {
if n > 0 {
panic("runtime: interface type cannot have methods")
}
ret := *underlying.InterfaceType()
ret.PkgPath_ = pkgPath
ret.Str_ = name
return &ret.Type
}
baseSize := hdrSizeOf(kind)
extraSize := uintptr(0)
if kind == abi.Func {
f := underlying.FuncType()
extraSize = uintptr(f.In()+f.Out()) * pointerSize
}
size := baseSize + extraSize
if n > 0 || pkgPath != "" {
size += uncommonTypeHdrSize + uintptr(n)*methodSize
tflag |= abi.TFlagUncommon
}
ptr := AllocU(size)
c.Memcpy(ptr, unsafe.Pointer(underlying), baseSize)
ret := (*Type)(ptr)
ret.TFlag = tflag | abi.TFlagNamed
ret.Str_ = name
xcount := 0
for _, m := range methods {
if !m.Exported() {
break
}
xcount++
}
uncommon := (*abi.UncommonType)(c.Advance(ptr, int(baseSize)))
uncommon.PkgPath_ = pkgPath
uncommon.Mcount = uint16(n)
uncommon.Xcount = uint16(xcount)
uncommon.Moff = uint32(uncommonTypeHdrSize + extraSize)
extraOff := int(baseSize + uncommonTypeHdrSize)
if extraSize > 0 {
src := c.Advance(unsafe.Pointer(underlying), int(baseSize))
dest := c.Advance(unsafe.Pointer(ptr), extraOff)
c.Memcpy(dest, src, extraSize)
extraOff += int(extraSize)
}
data := (*abi.Method)(c.Advance(ptr, extraOff))
copy(unsafe.Slice(data, n), methods)
return ret
}
// Func returns a function type. // Func returns a function type.
func Func(in, out []*Type, variadic bool) *FuncType { func Func(in, out []*Type, variadic bool) *FuncType {
n := len(in) + len(out) n := len(in) + len(out)
@@ -85,61 +178,8 @@ func Func(in, out []*Type, variadic bool) *FuncType {
return ret return ret
} }
// Imethod returns an interface method.
func Imethod(name string, typ *FuncType) abi.Imethod {
return abi.Imethod{
Name_: name,
Typ_: typ,
}
}
// Method returns a method.
func Method(name string, typ *FuncType, ifn, tfn abi.Text) abi.Method {
return abi.Method{
Name_: name,
Mtyp_: typ,
Ifn_: ifn,
Tfn_: tfn,
}
}
// Named returns a named type.
func Named(pkgPath, name string, underlying *Type, methods []abi.Method) *Type {
tflag := underlying.TFlag
size := typeHdrSize
n := len(methods)
if n > 0 || pkgPath != "" {
size += uncommonTypeHdrSize + uintptr(n)*methodSize
tflag |= abi.TFlagUncommon
}
ptr := AllocU(size)
ret := (*Type)(ptr)
*ret = *underlying
ret.TFlag = tflag | abi.TFlagNamed
ret.Str_ = name
xcount := 0
for _, m := range methods {
if !m.Exported() {
break
}
xcount++
}
uncommon := (*abi.UncommonType)(c.Advance(ptr, int(typeHdrSize)))
uncommon.PkgPath_ = pkgPath
uncommon.Mcount = uint16(n)
uncommon.Xcount = uint16(xcount)
uncommon.Moff = uint32(uncommonTypeHdrSize)
data := (*abi.Method)(c.Advance(ptr, int(typeHdrSize+uncommonTypeHdrSize)))
copy(unsafe.Slice(data, n), methods)
return ret
}
// Interface returns an interface type. // Interface returns an interface type.
func Interface(pkgPath string, methods []abi.Imethod) *Type { func Interface(pkgPath string, methods []abi.Imethod) *InterfaceType {
ret := &abi.InterfaceType{ ret := &abi.InterfaceType{
Type: Type{ Type: Type{
Size_: unsafe.Sizeof(eface{}), Size_: unsafe.Sizeof(eface{}),
@@ -149,7 +189,7 @@ func Interface(pkgPath string, methods []abi.Imethod) *Type {
PkgPath_: pkgPath, PkgPath_: pkgPath,
Methods: methods, Methods: methods,
} }
return &ret.Type return ret
} }
// NewItab returns a new itab. // NewItab returns a new itab.
@@ -158,7 +198,7 @@ func NewItab(inter *InterfaceType, typ *Type) *Itab {
size := itabHdrSize + uintptr(n)*pointerSize size := itabHdrSize + uintptr(n)*pointerSize
ptr := AllocU(size) ptr := AllocU(size)
ret := (*Itab)(ptr) ret := (*itab)(ptr)
ret.inter = inter ret.inter = inter
ret._type = typ ret._type = typ
ret.hash = typ.Hash ret.hash = typ.Hash

View File

@@ -69,3 +69,7 @@ func PrintSlice(s Slice) {
func PrintEface(e Eface) { func PrintEface(e Eface) {
print("(", e._type, ",", e.data, ")") print("(", e._type, ",", e.data, ")")
} }
func PrintIface(i Iface) {
print("(", i.tab, ",", i.data, ")")
}

View File

@@ -112,17 +112,22 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Pointer returns a pointer type. // PointerTo returns the pointer type with element elem.
func Pointer(elem *Type) *Type { func PointerTo(elem *Type) *Type {
ret := &abi.PtrType{ ret := elem.PtrToThis_
Type: Type{ if ret == nil {
Size_: unsafe.Sizeof(uintptr(0)), ptr := &abi.PtrType{
Hash: uint32(abi.Pointer), // TODO(xsw): hash Type: Type{
Kind_: uint8(abi.Pointer), Size_: unsafe.Sizeof(uintptr(0)),
}, Hash: uint32(abi.Pointer), // TODO(xsw): hash
Elem: elem, Kind_: uint8(abi.Pointer),
},
Elem: elem,
}
ret = &ptr.Type
elem.PtrToThis_ = ret
} }
return &ret.Type return ret
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"go/types" "go/types"
"hash" "hash"
"log"
"github.com/goplus/llgo/internal/abi" "github.com/goplus/llgo/internal/abi"
) )
@@ -92,7 +93,6 @@ func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) {
// Builder is a helper for constructing ABI types. // Builder is a helper for constructing ABI types.
type Builder struct { type Builder struct {
h hash.Hash
buf []byte buf []byte
Pkg string Pkg string
} }
@@ -106,7 +106,6 @@ func New(pkg string) *Builder {
func (b *Builder) Init(pkg string) { func (b *Builder) Init(pkg string) {
b.Pkg = pkg b.Pkg = pkg
b.h = sha256.New()
b.buf = make([]byte, sha256.Size) b.buf = make([]byte, sha256.Size)
} }
@@ -120,11 +119,19 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) {
return "*" + ret, pub return "*" + ret, pub
case *types.Struct: case *types.Struct:
return b.StructName(t) return b.StructName(t)
case *types.Signature:
return b.FuncName(t), true
case *types.Named: case *types.Named:
o := t.Obj() o := t.Obj()
return TypeName(o), o.Exported() return TypeName(o), o.Exported()
case *types.Interface:
if t.Empty() {
return "_llgo_any", true
}
return b.InterfaceName(t)
} }
panic("todo") log.Panicf("todo: %T\n", t)
return
} }
// PathOf returns the package path of the specified package. // PathOf returns the package path of the specified package.
@@ -150,6 +157,57 @@ func BasicName(t *types.Basic) string {
return "_llgo_" + t.Name() return "_llgo_" + t.Name()
} }
// FuncName returns the ABI type name for the specified function type.
func (b *Builder) FuncName(t *types.Signature) string {
hash := b.funcHash(t)
hashStr := base64.RawURLEncoding.EncodeToString(hash)
return "_llgo_func$" + hashStr
}
func (b *Builder) funcHash(t *types.Signature) []byte {
h := sha256.New()
params, results := t.Params(), t.Results()
fmt.Fprintln(h, "func", params.Len(), results.Len(), t.Variadic())
b.tuple(h, params)
b.tuple(h, results)
return h.Sum(b.buf[:0])
}
func (b *Builder) tuple(h hash.Hash, t *types.Tuple) {
n := t.Len()
for i := 0; i < n; i++ {
v := t.At(i)
ft, _ := b.TypeName(v.Type())
fmt.Fprintln(h, ft)
}
}
// InterfaceName returns the ABI type name for the specified interface type.
func (b *Builder) InterfaceName(t *types.Interface) (ret string, pub bool) {
hash, private := b.interfaceHash(t)
hashStr := base64.RawURLEncoding.EncodeToString(hash)
if private {
return b.Pkg + ".iface$" + hashStr, false
}
return "_llgo_iface$" + hashStr, true
}
func (b *Builder) interfaceHash(t *types.Interface) (ret []byte, private bool) {
h := sha256.New()
n := t.NumMethods()
fmt.Fprintln(h, "interface", n)
for i := 0; i < n; i++ {
m := t.Method(i)
if !m.Exported() {
private = true
}
ft := b.FuncName(m.Type().(*types.Signature))
fmt.Fprintln(h, m.Name(), ft)
}
ret = h.Sum(b.buf[:0])
return
}
// StructName returns the ABI type name for the specified struct type. // StructName returns the ABI type name for the specified struct type.
func (b *Builder) StructName(t *types.Struct) (ret string, pub bool) { func (b *Builder) StructName(t *types.Struct) (ret string, pub bool) {
hash, private := b.structHash(t) hash, private := b.structHash(t)
@@ -161,8 +219,7 @@ func (b *Builder) StructName(t *types.Struct) (ret string, pub bool) {
} }
func (b *Builder) structHash(t *types.Struct) (ret []byte, private bool) { func (b *Builder) structHash(t *types.Struct) (ret []byte, private bool) {
h := b.h h := sha256.New()
h.Reset()
n := t.NumFields() n := t.NumFields()
fmt.Fprintln(h, "struct", n) fmt.Fprintln(h, "struct", n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
@@ -174,10 +231,7 @@ func (b *Builder) structHash(t *types.Struct) (ret []byte, private bool) {
if f.Embedded() { if f.Embedded() {
name = "-" name = "-"
} }
ft, pub := b.TypeName(f.Type()) ft, _ := b.TypeName(f.Type())
if !pub {
private = true
}
fmt.Fprintln(h, name, ft) fmt.Fprintln(h, name, ft)
} }
ret = h.Sum(b.buf[:0]) ret = h.Sum(b.buf[:0])

View File

@@ -193,12 +193,6 @@ func (b Builder) Str(v string) (ret Expr) {
return Expr{aggregateValue(b.impl, prog.rtString(), data, size), prog.String()} return Expr{aggregateValue(b.impl, prog.rtString(), data, size), prog.String()}
} }
func (b Builder) pkgName(pkgPath string) Expr {
// TODO(xsw): use a global cache
// return b.Call(b.Pkg.rtFunc("NewPkgName"), b.Str(pkgPath))
return b.Str(pkgPath)
}
// unsafeString(data *byte, size int) string // unsafeString(data *byte, size int) string
func (b Builder) unsafeString(data, size llvm.Value) Expr { func (b Builder) unsafeString(data, size llvm.Value) Expr {
prog := b.Prog prog := b.Prog
@@ -906,7 +900,7 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
return b.Call(fn, args...) return b.Call(fn, args...)
} }
// The Call instruction represents a function or method call. // The Call instruction represents a function call.
// //
// The Call instruction yields the function result if there is exactly // The Call instruction yields the function result if there is exactly
// one. Otherwise it returns a tuple, the components of which are // one. Otherwise it returns a tuple, the components of which are
@@ -916,7 +910,6 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) {
// //
// t2 = println(t0, t1) // t2 = println(t0, t1)
// t4 = t3() // t4 = t3()
// t7 = invoke t5.Println(...t6)
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
@@ -954,7 +947,7 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
sig = raw.(*types.Signature) sig = raw.(*types.Signature)
ll = fn.ll ll = fn.ll
default: default:
panic("unreachable") log.Panicf("unreachable: %d(%T)\n", kind, raw)
} }
ret.Type = prog.retType(sig) ret.Type = prog.retType(sig)
ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sig.Params(), b)) ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sig.Params(), b))
@@ -1077,17 +1070,18 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
typ = prog.Float64() typ = prog.Float64()
case vkSlice: case vkSlice:
fn = "PrintSlice" fn = "PrintSlice"
case vkPtr, vkFuncPtr, vkFuncDecl:
fn = "PrintPointer"
typ = prog.VoidPtr()
case vkClosure: case vkClosure:
arg = b.Field(arg, 0) arg = b.Field(arg, 0)
fallthrough
case vkPtr, vkFuncPtr, vkFuncDecl:
fn = "PrintPointer" fn = "PrintPointer"
typ = prog.VoidPtr() typ = prog.VoidPtr()
case vkString: case vkString:
fn = "PrintString" fn = "PrintString"
case vkEface: case vkEface:
fn = "PrintEface" fn = "PrintEface"
case vkIface:
fn = "PrintIface"
// case vkComplex: // case vkComplex:
// fn = "PrintComplex" // fn = "PrintComplex"
default: default:

View File

@@ -55,28 +55,79 @@ func (b Builder) abiTypeOf(t types.Type) Expr {
return b.abiStructOf(t) return b.abiStructOf(t)
case *types.Named: case *types.Named:
return b.abiNamedOf(t) return b.abiNamedOf(t)
case *types.Interface:
return b.abiInterfaceOf(t)
case *types.Signature:
return b.abiFuncOf(t)
} }
panic("todo") panic("todo")
} }
func (b Builder) abiTupleOf(t *types.Tuple) Expr {
n := t.Len()
prog := b.Prog
tSlice := prog.Slice(prog.AbiTypePtr())
tuple := make([]Expr, n)
for i := 0; i < n; i++ {
tuple[i] = b.abiType(t.At(i).Type())
}
return b.SliceLit(tSlice, tuple...)
}
// func Func(in, out []*Type, variadic bool)
func (b Builder) abiFuncOf(sig *types.Signature) Expr {
prog := b.Prog
pkg := b.Pkg
fn := pkg.rtFunc("Func")
params := b.abiTupleOf(sig.Params())
results := b.abiTupleOf(sig.Results())
variadic := prog.Val(sig.Variadic())
return b.Call(fn, params, results, variadic)
}
// Imethod{name string, typ *FuncType}
func (b Builder) abiImethodOf(m *types.Func) Expr {
prog := b.Prog
name := b.Str(m.Name())
typ := b.abiType(m.Type())
return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl)
}
// func Interface(pkgPath string, methods []abi.Imethod)
func (b Builder) abiInterfaceOf(t *types.Interface) Expr {
prog := b.Prog
n := t.NumMethods()
methods := make([]Expr, n)
for i := 0; i < n; i++ {
m := t.Method(i)
methods[i] = b.abiImethodOf(m)
}
pkg := b.Pkg
fn := pkg.rtFunc("Interface")
pkgPath := pkg.Path()
tSlice := lastParamType(prog, fn)
methodSlice := b.SliceLit(tSlice, methods...)
return b.Call(fn, b.Str(pkgPath), methodSlice)
}
// func Named(pkgPath, name string, underlying *Type, methods []abi.Method) // func Named(pkgPath, name string, underlying *Type, methods []abi.Method)
func (b Builder) abiNamedOf(t *types.Named) Expr { func (b Builder) abiNamedOf(t *types.Named) Expr {
under := b.abiTypeOf(t.Underlying()) under := b.abiTypeOf(t.Underlying())
path := abi.PathOf(t.Obj().Pkg())
name := NameOf(t) name := NameOf(t)
prog := b.Prog prog := b.Prog
pkg := b.Pkg pkg := b.Pkg
pkgPath := b.pkgName(pkg.Path())
fn := pkg.rtFunc("Named") fn := pkg.rtFunc("Named")
tSlice := lastParamType(prog, fn) tSlice := lastParamType(prog, fn)
// TODO(xsw): methods // TODO(xsw): methods
methods := prog.Zero(tSlice) methods := prog.Zero(tSlice)
return b.Call(fn, pkgPath, b.Str(name), under, methods) return b.Call(fn, b.Str(path), b.Str(name), under, methods)
} }
func (b Builder) abiPointerOf(t *types.Pointer) Expr { func (b Builder) abiPointerOf(t *types.Pointer) Expr {
elem := b.abiTypeOf(t.Elem()) elem := b.abiTypeOf(t.Elem())
return b.Call(b.Pkg.rtFunc("Pointer"), elem) return b.Call(b.Pkg.rtFunc("PointerTo"), elem)
} }
// func Struct(pkgPath string, size uintptr, fields []abi.StructField) // func Struct(pkgPath string, size uintptr, fields []abi.StructField)
@@ -93,7 +144,7 @@ func (b Builder) abiStructOf(t *types.Struct) Expr {
off := uintptr(prog.OffsetOf(typ, i)) off := uintptr(prog.OffsetOf(typ, i))
flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(i)) flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(i))
} }
pkgPath := b.pkgName(pkg.Path()) pkgPath := b.Str(pkg.Path())
tSlice := lastParamType(prog, strucAbi) tSlice := lastParamType(prog, strucAbi)
fldSlice := b.SliceLit(tSlice, flds...) fldSlice := b.SliceLit(tSlice, flds...)
size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr()) size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr())
@@ -156,6 +207,50 @@ func (b Builder) unsafeEface(t, data llvm.Value) llvm.Value {
return aggregateValue(b.impl, b.Prog.rtEface(), t, data) return aggregateValue(b.impl, b.Prog.rtEface(), t, data)
} }
// unsafeIface(itab *runtime.Itab, data unsafe.Pointer) Eface
func (b Builder) unsafeIface(itab, data llvm.Value) llvm.Value {
return aggregateValue(b.impl, b.Prog.rtIface(), itab, data)
}
// func NewItab(tintf *InterfaceType, typ *Type) *runtime.Itab
func (b Builder) newItab(tintf, typ Expr) Expr {
return b.Call(b.Pkg.rtFunc("NewItab"), tintf, typ)
}
func (b Builder) unsafeInterface(rawIntf *types.Interface, t Expr, data llvm.Value) llvm.Value {
if rawIntf.Empty() {
return b.unsafeEface(t.impl, data)
}
tintf := b.abiType(rawIntf)
itab := b.newItab(tintf, t)
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 // MakeInterface constructs an instance of an interface type from a
@@ -185,7 +280,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
case abi.Indirect: case abi.Indirect:
vptr := b.AllocU(typ) vptr := b.AllocU(typ)
b.Store(vptr, x) b.Store(vptr, x)
return Expr{b.unsafeEface(tabi.impl, vptr.impl), tinter} return Expr{b.unsafeInterface(rawIntf, tabi, vptr.impl), tinter}
} }
ximpl := x.impl ximpl := x.impl
if lvl > 0 { if lvl > 0 {
@@ -194,7 +289,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
var u llvm.Value var u llvm.Value
switch kind { switch kind {
case abi.Pointer: case abi.Pointer:
return Expr{b.unsafeEface(tabi.impl, ximpl), tinter} return Expr{b.unsafeInterface(rawIntf, tabi, ximpl), tinter}
case abi.Integer: case abi.Integer:
tu := prog.Uintptr() tu := prog.Uintptr()
u = llvm.CreateIntCast(b.impl, ximpl, tu.ll) u = llvm.CreateIntCast(b.impl, ximpl, tu.ll)
@@ -205,7 +300,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
panic("todo") panic("todo")
} }
data := llvm.CreateIntToPtr(b.impl, u, prog.tyVoidPtr()) data := llvm.CreateIntToPtr(b.impl, u, prog.tyVoidPtr())
return Expr{b.unsafeEface(tabi.impl, data), tinter} return Expr{b.unsafeInterface(rawIntf, tabi, data), tinter}
} }
func (b Builder) valFromData(typ Type, data llvm.Value) Expr { func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
@@ -357,6 +452,10 @@ func (b Builder) faceData(x llvm.Value) llvm.Value {
return llvm.CreateExtractValue(b.impl, x, 1) 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 { func (b Builder) faceAbiType(x Expr) Expr {
if x.kind == vkIface { if x.kind == vkIface {
panic("todo") panic("todo")

View File

@@ -125,12 +125,14 @@ type aProgram struct {
rtStringTy llvm.Type rtStringTy llvm.Type
rtEfaceTy llvm.Type rtEfaceTy llvm.Type
rtIfaceTy llvm.Type
rtSliceTy llvm.Type rtSliceTy llvm.Type
rtMapTy llvm.Type rtMapTy llvm.Type
anyTy Type anyTy Type
voidTy Type voidTy Type
voidPtr Type voidPtr Type
voidPPtr Type
boolTy Type boolTy Type
cstrTy Type cstrTy Type
cintTy Type cintTy Type
@@ -149,7 +151,6 @@ type aProgram struct {
pyObjPPtr Type pyObjPPtr Type
abiTyptr Type abiTyptr Type
abiTypptr Type abiTypptr Type
//efaceTy Type
pyImpTy *types.Signature pyImpTy *types.Signature
pyNewList *types.Signature pyNewList *types.Signature
@@ -256,6 +257,13 @@ func (p Program) rtEface() llvm.Type {
return p.rtEfaceTy return p.rtEfaceTy
} }
func (p Program) rtIface() llvm.Type {
if p.rtIfaceTy.IsNil() {
p.rtIfaceTy = p.rtType("Iface").ll
}
return p.rtIfaceTy
}
func (p Program) rtMap() llvm.Type { func (p Program) rtMap() llvm.Type {
if p.rtMapTy.IsNil() { if p.rtMapTy.IsNil() {
p.rtMapTy = p.rtType("Map").ll p.rtMapTy = p.rtType("Map").ll
@@ -364,6 +372,13 @@ func (p Program) VoidPtr() Type {
return p.voidPtr 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. // Bool returns bool type.
func (p Program) Bool() Type { func (p Program) Bool() Type {
if p.boolTy == nil { if p.boolTy == nil {

View File

@@ -274,6 +274,7 @@ func (p Program) toType(raw types.Type) Type {
if t.Empty() { if t.Empty() {
return &aType{p.rtEface(), typ, vkEface} return &aType{p.rtEface(), typ, vkEface}
} }
return &aType{p.rtIface(), typ, vkIface}
case *types.Slice: case *types.Slice:
return &aType{p.rtSlice(), typ, vkSlice} return &aType{p.rtSlice(), typ, vkSlice}
case *types.Map: case *types.Map:

View File

@@ -66,27 +66,6 @@ func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl} 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. // Closure creates a closture type for a function.
func (p Program) Closure(fn Type) Type { func (p Program) Closure(fn Type) Type {
sig := fn.raw.Type.(*types.Signature) sig := fn.raw.Type.(*types.Signature)