cl: _testcgo/struct

This commit is contained in:
xushiwei
2024-04-27 07:47:10 +08:00
parent c455f6e730
commit 5f08e7a612
7 changed files with 148 additions and 82 deletions

25
cl/_testcgo/struct/in.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "C"
import _ "unsafe"
//go:linkname printf C.printf
func printf(format *int8, __llgo_va_list ...any)
type Foo struct {
A C.int
ok bool
}
var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0}
func (p *Foo) Print() {
if p.ok {
printf(&format[0], p.A)
}
}
func main() {
foo := Foo{100, true}
foo.Print()
}

60
cl/_testcgo/struct/out.ll Normal file
View File

@@ -0,0 +1,60 @@
; ModuleID = 'main'
source_filename = "main"
%main.Foo = type { i32, i1 }
@main.format = global ptr null
@"main.init$guard" = global ptr null
define void @"(*main.Foo).Print"(ptr %0) {
_llgo_0:
%1 = getelementptr inbounds i1, ptr %0, i32 0, i32 1
%2 = load i1, ptr %1, align 1
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
%3 = getelementptr inbounds i32, ptr %0, i32 0, i32 0
%4 = load i32, ptr %3, align 4
call void (ptr, ...) @printf(ptr @main.format, i32 %4)
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
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 void @main() {
_llgo_0:
call void @main.init()
%0 = alloca %main.Foo, align 8
%1 = getelementptr inbounds i32, ptr %0, i32 0, i32 0
%2 = getelementptr inbounds i1, ptr %0, i32 0, i32 1
store i32 100, ptr %1, align 4
store i1 true, ptr %2, align 1
call void @"(*main.Foo).Print"(ptr %0)
ret void
}
declare void @printf(ptr, ...)

View File

@@ -139,7 +139,7 @@ func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
tn := t.Object().(*types.TypeName)
tnName := tn.Name()
typ := tn.Type()
name := fullName(tn.Pkg(), tnName)
name := llssa.FullName(tn.Pkg(), tnName)
if ignoreName(name) {
return
}
@@ -164,7 +164,7 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) {
// Global variable.
func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
typ := gbl.Type()
name := fullName(gbl.Pkg.Pkg, gbl.Name())
name := llssa.FullName(gbl.Pkg.Pkg, gbl.Name())
if ignoreName(name) || checkCgo(gbl.Name()) {
return
}
@@ -300,6 +300,9 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
t := v.Type()
x := p.compileValue(b, v.X)
ret = b.ChangeType(p.prog.Type(t), x)
case *ssa.FieldAddr:
x := p.compileValue(b, v.X)
ret = b.FieldAddr(x, v.Field)
case *ssa.IndexAddr:
vx := v.X
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
@@ -452,7 +455,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll
pkgProg := pkg.Prog
pkgTypes := pkg.Pkg
pkgName, pkgPath := pkgTypes.Name(), pathOf(pkgTypes)
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
ret = prog.NewPackage(pkgName, pkgPath)
ctx := &context{

View File

@@ -51,7 +51,7 @@ func (p *context) importPkg(pkg *types.Package) {
fset := p.fset
names := scope.Names()
contents := make(contentMap)
pkgPath := pathOf(pkg)
pkgPath := llssa.PathOf(pkg)
for _, name := range names {
if token.IsExported(name) {
obj := scope.Lookup(name)
@@ -109,17 +109,6 @@ func (p *context) initLinkname(pkgPath, line string) {
}
}
func pathOf(pkg *types.Package) string {
if pkg.Name() == "main" {
return "main"
}
return pkg.Path()
}
func fullName(pkg *types.Package, name string) string {
return pathOf(pkg) + "." + name
}
// func: pkg.name
// method: (pkg.T).name, (*pkg.T).name
func funcName(pkg *types.Package, fn *ssa.Function) string {
@@ -131,10 +120,10 @@ func funcName(pkg *types.Package, fn *ssa.Function) string {
if tp, ok := t.(*types.Pointer); ok {
t, tName = tp.Elem(), "*"
}
tName += t.(*types.Named).Obj().Name()
tName += llssa.NameOf(t.(*types.Named))
return "(" + tName + ")." + name
}
ret := fullName(pkg, name)
ret := llssa.FullName(pkg, name)
if ret == "main.main" {
ret = "main"
}
@@ -171,7 +160,7 @@ func (p *context) funcOf(fn *ssa.Function) llssa.Function {
func (p *context) varOf(v *ssa.Global) llssa.Global {
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
pkg := p.pkg
name := fullName(pkgTypes, v.Name())
name := llssa.FullName(pkgTypes, v.Name())
if ret := pkg.VarOf(name); ret != nil {
return ret
}

View File

@@ -1,62 +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 cl
/*
// Define unimplemented intrinsic functions.
//
// Some functions are either normally implemented in Go assembly (like
// sync/atomic functions) or intentionally left undefined to be implemented
// directly in the compiler (like runtime/volatile functions). Either way, look
// for these and implement them if this is the case.
func (b *builder) defineIntrinsicFunction() {
panic("todo")
}
var mathToLLVMMapping = map[string]string{
"math.Ceil": "llvm.ceil.f64",
"math.Exp": "llvm.exp.f64",
"math.Exp2": "llvm.exp2.f64",
"math.Floor": "llvm.floor.f64",
"math.Log": "llvm.log.f64",
"math.Sqrt": "llvm.sqrt.f64",
"math.Trunc": "llvm.trunc.f64",
}
// defineMathOp defines a math function body as a call to a LLVM intrinsic,
// instead of the regular Go implementation. This allows LLVM to reason about
// the math operation and (depending on the architecture) allows it to lower the
// operation to very fast floating point instructions. If this is not possible,
// LLVM will emit a call to a libm function that implements the same operation.
//
// One example of an optimization that LLVM can do is to convert
// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
// beneficial on architectures where 64-bit floating point operations are (much)
// more expensive than 32-bit ones.
func (b *builder) defineMathOp() {
panic("todo")
}
// Implement most math/bits functions.
//
// This implements all the functions that operate on bits. It does not yet
// implement the arithmetic functions (like bits.Add), which also have LLVM
// intrinsics.
func (b *builder) defineMathBitsIntrinsic() bool {
panic("todo")
}
*/