cl: pkgKind = normal/noinit/decl
This commit is contained in:
@@ -11,7 +11,6 @@ _llgo_0:
|
||||
|
||||
_llgo_1: ; preds = %_llgo_0
|
||||
store i1 true, ptr @"main.init$guard", align 1
|
||||
call void @"github.com/goplus/llgo/cl/internal/libc.init"()
|
||||
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
|
||||
@@ -36,8 +35,6 @@ _llgo_0:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @"github.com/goplus/llgo/cl/internal/libc.init"()
|
||||
|
||||
declare i32 @strlen(ptr)
|
||||
|
||||
declare void @"github.com/goplus/llgo/cl/internal/libc.Printf"(ptr, ...)
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestIgnoreName(t *testing.T) {
|
||||
func TestErrImport(t *testing.T) {
|
||||
var ctx context
|
||||
pkg := types.NewPackage("foo", "foo")
|
||||
ctx.importPkg(pkg)
|
||||
ctx.importPkg(pkg, nil)
|
||||
}
|
||||
|
||||
func TestErrInitLinkname(t *testing.T) {
|
||||
|
||||
@@ -61,12 +61,12 @@ const (
|
||||
fnIgnore
|
||||
)
|
||||
|
||||
func funcKind(vfn ssa.Value) int {
|
||||
func (p *context) funcKind(vfn ssa.Value) int {
|
||||
if fn, ok := vfn.(*ssa.Function); ok && fn.Signature.Recv() == nil {
|
||||
params := fn.Signature.Params()
|
||||
n := params.Len()
|
||||
if n == 0 {
|
||||
if fn.Name() == "init" && ignorePkgInit(fn.Pkg.Pkg.Path()) {
|
||||
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
||||
return fnIgnore
|
||||
}
|
||||
} else {
|
||||
@@ -79,10 +79,10 @@ func funcKind(vfn ssa.Value) int {
|
||||
return fnNormal
|
||||
}
|
||||
|
||||
func ignorePkgInit(pkgPath string) bool {
|
||||
switch pkgPath {
|
||||
case "unsafe", "syscall", "runtime/cgo":
|
||||
return true
|
||||
func (p *context) pkgNoInit(pkg *types.Package) bool {
|
||||
p.ensureLoaded(pkg)
|
||||
if i, ok := p.loaded[pkg]; ok {
|
||||
return i.kind != pkgNormal
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -113,13 +113,21 @@ func inPkg(name, pkg string) bool {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type none = struct{}
|
||||
|
||||
type instrOrValue interface {
|
||||
ssa.Instruction
|
||||
ssa.Value
|
||||
}
|
||||
|
||||
const (
|
||||
pkgNormal = iota
|
||||
pkgNoInit // noinit: a package that don't need to be initialized
|
||||
pkgDeclOnly // decl: a package that only have declarations
|
||||
)
|
||||
|
||||
type pkgInfo struct {
|
||||
kind int
|
||||
}
|
||||
|
||||
type context struct {
|
||||
prog llssa.Program
|
||||
pkg llssa.Package
|
||||
@@ -129,7 +137,7 @@ type context struct {
|
||||
goTyps *types.Package
|
||||
goPkg *ssa.Package
|
||||
link map[string]string // pkgPath.nameInPkg => linkname
|
||||
loaded map[*types.Package]none // loaded packages
|
||||
loaded map[*types.Package]*pkgInfo // loaded packages
|
||||
bvals map[ssa.Value]llssa.Expr // block values
|
||||
vargs map[*ssa.Alloc][]llssa.Expr // varargs
|
||||
inits []func()
|
||||
@@ -271,7 +279,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
||||
case *ssa.Call:
|
||||
call := v.Call
|
||||
cv := call.Value
|
||||
kind := funcKind(cv)
|
||||
kind := p.funcKind(cv)
|
||||
if kind == fnIgnore {
|
||||
return
|
||||
}
|
||||
@@ -484,8 +492,10 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
|
||||
goTyps: pkgTypes,
|
||||
goPkg: pkg,
|
||||
link: make(map[string]string),
|
||||
loaded: make(map[*types.Package]none),
|
||||
vargs: make(map[*ssa.Alloc][]llssa.Expr),
|
||||
loaded: map[*types.Package]*pkgInfo{
|
||||
types.Unsafe: {kind: pkgNoInit}, // TODO(xsw): pkgNoInit or pkgDeclOnly?
|
||||
},
|
||||
}
|
||||
ctx.initFiles(pkgPath, files)
|
||||
for _, m := range members {
|
||||
|
||||
36
cl/import.go
36
cl/import.go
@@ -19,6 +19,7 @@ package cl
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
@@ -43,11 +44,27 @@ func contentOf(m contentMap, file string) (lines contentLines, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *context) importPkg(pkg *types.Package) {
|
||||
// decl: a package that only contains declarations
|
||||
// noinit: a package that does not need to be initialized
|
||||
func pkgKind(v string) int {
|
||||
switch v {
|
||||
case "decl":
|
||||
return pkgDeclOnly
|
||||
case "noinit":
|
||||
return pkgNoInit
|
||||
}
|
||||
return pkgNormal
|
||||
}
|
||||
|
||||
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
||||
scope := pkg.Scope()
|
||||
if scope.Lookup("LLGoPackage") == nil {
|
||||
llpkg, ok := scope.Lookup("LLGoPackage").(*types.Const)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if v := llpkg.Val(); v.Kind() == constant.String {
|
||||
i.kind = pkgKind(constant.StringVal(v))
|
||||
}
|
||||
fset := p.fset
|
||||
names := scope.Names()
|
||||
contents := make(contentMap)
|
||||
@@ -170,9 +187,20 @@ func (p *context) varOf(v *ssa.Global) llssa.Global {
|
||||
func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package {
|
||||
if p.goTyps != pkgTypes {
|
||||
if _, ok := p.loaded[pkgTypes]; !ok {
|
||||
p.loaded[pkgTypes] = none{}
|
||||
p.importPkg(pkgTypes)
|
||||
i := &pkgInfo{
|
||||
kind: pkgKindByPath(pkgTypes.Path()),
|
||||
}
|
||||
p.loaded[pkgTypes] = i
|
||||
p.importPkg(pkgTypes, i)
|
||||
}
|
||||
}
|
||||
return pkgTypes
|
||||
}
|
||||
|
||||
func pkgKindByPath(pkgPath string) int {
|
||||
switch pkgPath {
|
||||
case "syscall", "runtime/cgo":
|
||||
return pkgNoInit
|
||||
}
|
||||
return pkgNormal
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import "C"
|
||||
import _ "unsafe"
|
||||
|
||||
const (
|
||||
LLGoPackage = true
|
||||
LLGoPackage = "decl"
|
||||
)
|
||||
|
||||
//go:linkname Printf C.printf
|
||||
|
||||
@@ -14,18 +14,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package runtime
|
||||
package c
|
||||
|
||||
import "unsafe"
|
||||
|
||||
const (
|
||||
LLGoPackage = true
|
||||
LLGoPackage = "decl"
|
||||
)
|
||||
|
||||
//go:linkname String llgo.CString
|
||||
func String(string) *int8
|
||||
|
||||
//go:linkname Alloca llgo.Alloca
|
||||
func Alloca(size uintptr) unsafe.Pointer
|
||||
|
||||
//go:linkname Unreachable llgo.Unreachable
|
||||
func Unreachable()
|
||||
|
||||
//go:linkname Malloc C.malloc
|
||||
func Malloc(size uintptr) unsafe.Pointer
|
||||
|
||||
// Alloc allocates memory.
|
||||
func Alloc(size uintptr) unsafe.Pointer {
|
||||
return Malloc(size)
|
||||
}
|
||||
//go:linkname Memcpy C.memcpy
|
||||
func Memcpy(dst, src unsafe.Pointer, n uintptr) unsafe.Pointer
|
||||
|
||||
//go:linkname Printf C.printf
|
||||
func Printf(format *int8, __llgo_va_list ...any)
|
||||
44
internal/runtime/z_c.go
Normal file
44
internal/runtime/z_c.go
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
"github.com/goplus/llgo/internal/runtime/c"
|
||||
)
|
||||
|
||||
// Alloc allocates memory.
|
||||
func Alloc(size uintptr) unsafe.Pointer {
|
||||
return c.Malloc(size)
|
||||
}
|
||||
|
||||
/*
|
||||
// Panic panics with a value.
|
||||
func Panic(v Interface) {
|
||||
c.Printf(c.String("Panic!!!\n"))
|
||||
kind := abi.Kind(v.tab._type.Kind_)
|
||||
switch {
|
||||
case kind == abi.String:
|
||||
s := (*String)(v.data)
|
||||
cs := c.Alloca(uintptr(s.len) + 1)
|
||||
c.Memcpy(cs, s.data, uintptr(s.len))
|
||||
(*[1 << 30]int8)(cs)[s.len] = 0
|
||||
c.Printf(c.String("%s\n"), cs)
|
||||
}
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user