builtin: real/imag/complex; c/math/cmplx; patch: math/cmplx

This commit is contained in:
xushiwei
2024-06-20 10:00:47 +08:00
parent 1566a834e1
commit de6535b722
9 changed files with 274 additions and 24 deletions

View File

@@ -206,8 +206,9 @@ Here are the Go packages that can be imported correctly:
* [unicode](https://pkg.go.dev/unicode) * [unicode](https://pkg.go.dev/unicode)
* [unicode/utf8](https://pkg.go.dev/unicode/utf8) * [unicode/utf8](https://pkg.go.dev/unicode/utf8)
* [unicode/utf16](https://pkg.go.dev/unicode/utf16) * [unicode/utf16](https://pkg.go.dev/unicode/utf16)
* [math/bits](https://pkg.go.dev/math/bits)
* [math](https://pkg.go.dev/math) * [math](https://pkg.go.dev/math)
* [math/bits](https://pkg.go.dev/math/bits)
* [math/cmplx](https://pkg.go.dev/math/cmplx)
* [syscall](https://pkg.go.dev/syscall) (partially) * [syscall](https://pkg.go.dev/syscall) (partially)
* [sync](https://pkg.go.dev/sync) (partially) * [sync](https://pkg.go.dev/sync) (partially)
* [sync/atomic](https://pkg.go.dev/sync/atomic) (partially) * [sync/atomic](https://pkg.go.dev/sync/atomic) (partially)
@@ -217,8 +218,8 @@ Here are the Go packages that can be imported correctly:
- [Go 1.20+](https://go.dev) (build only) - [Go 1.20+](https://go.dev) (build only)
- [LLVM 17](https://llvm.org) - [LLVM 17](https://llvm.org)
- [Clang 17](https://clang.llvm.org)
- [LLD 17](https://lld.llvm.org) - [LLD 17](https://lld.llvm.org)
- [Clang 17](https://clang.llvm.org)
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/) - [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/) - [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [`github.com/goplus/llgo/c/cjson`](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)) - [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [`github.com/goplus/llgo/c/cjson`](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))

9
_demo/complex/cmplx.go Normal file
View File

@@ -0,0 +1,9 @@
package main
import (
"math/cmplx"
)
func main() {
println("abs(3+4i):", cmplx.Abs(3+4i))
}

89
c/math/cmplx/complex.go Normal file
View File

@@ -0,0 +1,89 @@
/*
* 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 cmplx
import (
_ "unsafe"
)
const (
LLGoPackage = "decl"
)
// -----------------------------------------------------------------------------
//go:linkname Abs C.cabs
func Abs(z complex128) float64
//go:linkname Acos C.cacos
func Acos(z complex128) complex128
//go:linkname Acosh C.cacosh
func Acosh(z complex128) complex128
//go:linkname Asin C.casin
func Asin(z complex128) complex128
//go:linkname Asinh C.casinh
func Asinh(z complex128) complex128
//go:linkname Atan C.catan
func Atan(z complex128) complex128
//go:linkname Atanh C.catanh
func Atanh(z complex128) complex128
//go:linkname Cos C.ccos
func Cos(z complex128) complex128
//go:linkname Cosh C.ccosh
func Cosh(z complex128) complex128
//go:linkname Exp C.cexp
func Exp(z complex128) complex128
//go:linkname Log C.clog
func Log(z complex128) complex128
//go:linkname Log10 C.clog10
func Log10(z complex128) complex128
//go:linkname Arg C.carg
func Arg(z complex128) float64
//go:linkname Phase C.carg
func Phase(z complex128) float64
//go:linkname Pow C.cpow
func Pow(x, y complex128) complex128
//go:linkname Sin C.csin
func Sin(z complex128) complex128
//go:linkname Sinh C.csinh
func Sinh(z complex128) complex128
//go:linkname Sqrt C.csqrt
func Sqrt(z complex128) complex128
//go:linkname Tan C.ctan
func Tan(z complex128) complex128
//go:linkname Tanh C.ctanh
func Tanh(z complex128) complex128
// -----------------------------------------------------------------------------

View File

@@ -722,6 +722,7 @@ var hasAltPkg = map[string]none{
"io": {}, "io": {},
"io/fs": {}, "io/fs": {},
"math": {}, "math": {},
"math/cmplx": {},
"sync": {}, "sync": {},
"sync/atomic": {}, "sync/atomic": {},
"syscall": {}, "syscall": {},

View File

@@ -0,0 +1,86 @@
/*
* 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 cmplx
import (
_ "unsafe"
)
const (
LLGoPackage = true
)
// -----------------------------------------------------------------------------
//go:linkname Abs C.cabs
func Abs(z complex128) float64
//go:linkname Acos C.cacos
func Acos(z complex128) complex128
//go:linkname Acosh C.cacosh
func Acosh(z complex128) complex128
//go:linkname Asin C.casin
func Asin(z complex128) complex128
//go:linkname Asinh C.casinh
func Asinh(z complex128) complex128
//go:linkname Atan C.catan
func Atan(z complex128) complex128
//go:linkname Atanh C.catanh
func Atanh(z complex128) complex128
//go:linkname Cos C.ccos
func Cos(z complex128) complex128
//go:linkname Cosh C.ccosh
func Cosh(z complex128) complex128
//go:linkname Exp C.cexp
func Exp(z complex128) complex128
//go:linkname Log C.clog
func Log(z complex128) complex128
//go:linkname Log10 C.clog10
func Log10(z complex128) complex128
//go:linkname Phase C.carg
func Phase(z complex128) float64
//go:linkname Pow C.cpow
func Pow(x, y complex128) complex128
//go:linkname Sin C.csin
func Sin(z complex128) complex128
//go:linkname Sinh C.csinh
func Sinh(z complex128) complex128
//go:linkname Sqrt C.csqrt
func Sqrt(z complex128) complex128
//go:linkname Tan C.ctan
func Tan(z complex128) complex128
//go:linkname Tanh C.ctanh
func Tanh(z complex128) complex128
// -----------------------------------------------------------------------------

View File

@@ -66,6 +66,21 @@ func (b Builder) getField(x Expr, idx int) Expr {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
func (b Builder) Complex(r, i Expr) Expr {
if debugInstr {
log.Printf("Complex %v, %v\n", r.impl, i.impl)
}
prog := b.Prog
var t Type
switch kind := r.raw.Type.Underlying().(*types.Basic).Kind(); kind {
case types.Float64:
t = prog.Complex128()
case types.Float32:
t = prog.Complex64()
}
return b.aggregateValue(t, r.impl, i.impl)
}
// MakeString creates a new string from a C string pointer and length. // MakeString creates a new string from a C string pointer and length.
func (b Builder) MakeString(cstr Expr, n ...Expr) (ret Expr) { func (b Builder) MakeString(cstr Expr, n ...Expr) (ret Expr) {
if debugInstr { if debugInstr {

View File

@@ -168,11 +168,20 @@ func (p Program) IntVal(v uint64, t Type) Expr {
return Expr{ret, t} return Expr{ret, t}
} }
// FloatVal returns a float constant expression.
func (p Program) FloatVal(v float64, t Type) Expr { func (p Program) FloatVal(v float64, t Type) Expr {
ret := llvm.ConstFloat(t.ll, v) ret := llvm.ConstFloat(t.ll, v)
return Expr{ret, t} return Expr{ret, t}
} }
// ComplexVal returns a complex constant expression.
func (p Program) ComplexVal(v complex128, t Type) Expr {
flt := p.Field(t, 0)
re := p.FloatVal(real(v), flt)
im := p.FloatVal(imag(v), flt)
return Expr{llvm.ConstStruct([]llvm.Value{re.impl, im.impl}, false), t}
}
// Val returns a constant expression. // Val returns a constant expression.
func (p Program) Val(v interface{}) Expr { func (p Program) Val(v interface{}) Expr {
switch v := v.(type) { switch v := v.(type) {
@@ -211,11 +220,16 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
if v, exact := constant.Uint64Val(v); exact { if v, exact := constant.Uint64Val(v); exact {
return prog.IntVal(v, typ) return prog.IntVal(v, typ)
} }
case kind == types.Float32 || kind == types.Float64: case kind == types.Float64 || kind == types.Float32:
v, _ := constant.Float64Val(v) v, _ := constant.Float64Val(v)
return prog.FloatVal(v, typ) return prog.FloatVal(v, typ)
case kind == types.String: case kind == types.String:
return Expr{b.Str(constant.StringVal(v)).impl, typ} return Expr{b.Str(constant.StringVal(v)).impl, typ}
case kind == types.Complex128 || kind == types.Complex64:
v = constant.ToComplex(v)
re, _ := constant.Float64Val(constant.Real(v))
im, _ := constant.Float64Val(constant.Imag(v))
return prog.ComplexVal(complex(re, im), typ)
} }
} }
panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw)) panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw))
@@ -941,6 +955,12 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
return b.Recover() return b.Recover()
case "print", "println": case "print", "println":
return b.PrintEx(fn == "println", args...) return b.PrintEx(fn == "println", args...)
case "complex":
return b.Complex(args[0], args[1])
case "real":
return b.getField(args[0], 0)
case "imag":
return b.getField(args[0], 1)
case "String": // unsafe.String case "String": // unsafe.String
return b.unsafeString(args[0].impl, args[1].impl) return b.unsafeString(args[0].impl, args[1].impl)
case "Slice": // unsafe.Slice case "Slice": // unsafe.Slice

View File

@@ -125,6 +125,9 @@ type aProgram struct {
voidType llvm.Type voidType llvm.Type
voidPtrTy llvm.Type voidPtrTy llvm.Type
c64Type llvm.Type
c128Type llvm.Type
rtStringTy llvm.Type rtStringTy llvm.Type
rtEfaceTy llvm.Type rtEfaceTy llvm.Type
rtIfaceTy llvm.Type rtIfaceTy llvm.Type
@@ -132,8 +135,6 @@ type aProgram struct {
rtMapTy llvm.Type rtMapTy llvm.Type
anyTy Type anyTy Type
//anyPtr Type
//anyPPtr Type
voidTy Type voidTy Type
voidPtr Type voidPtr Type
voidPPtr Type voidPPtr Type
@@ -147,6 +148,8 @@ type aProgram struct {
uintTy Type uintTy Type
f64Ty Type f64Ty Type
f32Ty Type f32Ty Type
c128Ty Type
c64Ty Type
byteTy Type byteTy Type
i32Ty Type i32Ty Type
u32Ty Type u32Ty Type
@@ -284,6 +287,24 @@ func (p Program) rtString() llvm.Type {
return p.rtStringTy return p.rtStringTy
} }
func (p Program) tyComplex64() llvm.Type {
if p.c64Type.IsNil() {
ctx := p.ctx
f32 := ctx.FloatType()
p.c64Type = ctx.StructType([]llvm.Type{f32, f32}, false)
}
return p.c64Type
}
func (p Program) tyComplex128() llvm.Type {
if p.c128Type.IsNil() {
ctx := p.ctx
f64 := ctx.DoubleType()
p.c128Type = ctx.StructType([]llvm.Type{f64, f64}, false)
}
return p.c128Type
}
// NewPackage creates a new package. // NewPackage creates a new package.
func (p Program) NewPackage(name, pkgPath string) Package { func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath) mod := p.ctx.NewModule(pkgPath)
@@ -394,24 +415,6 @@ func (p Program) String() Type {
return p.stringTy return p.stringTy
} }
/*
// AnyPtrPtr returns **any type.
func (p Program) AnyPtrPtr() Type {
if p.anyPPtr == nil {
p.anyPPtr = p.Pointer(p.AnyPtr())
}
return p.anyPPtr
}
// AnyPtr returns *any type.
func (p Program) AnyPtr() Type {
if p.anyPtr == nil {
p.anyPtr = p.Pointer(p.Any())
}
return p.anyPtr
}
*/
// Any returns the any (empty interface) type. // Any returns the any (empty interface) type.
func (p Program) Any() Type { func (p Program) Any() Type {
if p.anyTy == nil { if p.anyTy == nil {
@@ -484,6 +487,22 @@ func (p Program) Float32() Type {
return p.f32Ty return p.f32Ty
} }
// Complex128 returns complex128 type.
func (p Program) Complex128() Type {
if p.c128Ty == nil {
p.c128Ty = p.rawType(types.Typ[types.Complex128])
}
return p.c128Ty
}
// Complex64 returns complex64 type.
func (p Program) Complex64() Type {
if p.c64Ty == nil {
p.c64Ty = p.rawType(types.Typ[types.Complex64])
}
return p.c64Ty
}
// Byte returns byte type. // Byte returns byte type.
func (p Program) Byte() Type { func (p Program) Byte() Type {
if p.byteTy == nil { if p.byteTy == nil {

View File

@@ -214,6 +214,14 @@ func (p Program) Field(typ Type, i int) Type {
switch t := typ.raw.Type.(type) { switch t := typ.raw.Type.(type) {
case *types.Tuple: case *types.Tuple:
fld = t.At(i) fld = t.At(i)
case *types.Basic:
switch t.Kind() {
case types.Complex128:
return p.Float64()
case types.Complex64:
return p.Float32()
}
panic("Field: basic type doesn't have fields")
default: default:
fld = t.Underlying().(*types.Struct).Field(i) fld = t.Underlying().(*types.Struct).Field(i)
} }
@@ -330,7 +338,9 @@ func (p Program) toType(raw types.Type) Type {
case types.Float64: case types.Float64:
return &aType{p.ctx.DoubleType(), typ, vkFloat} return &aType{p.ctx.DoubleType(), typ, vkFloat}
case types.Complex64: case types.Complex64:
return &aType{p.tyComplex64(), typ, vkComplex}
case types.Complex128: case types.Complex128:
return &aType{p.tyComplex128(), typ, vkComplex}
case types.String: case types.String:
return &aType{p.rtString(), typ, vkString} return &aType{p.rtString(), typ, vkString}
case types.UnsafePointer: case types.UnsafePointer: