diff --git a/README.md b/README.md index 9628e7979..05ecaf0b1 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,6 @@ Common Go syntax is already supported. Except for the following, which needs to * map (Very limited support) * chan (Not supported yet) -* generics (Not supported yet) Here are some examples related to Go syntax: @@ -212,7 +211,7 @@ Here are the Go packages that can be imported correctly: * [strconv](https://pkg.go.dev/strconv) * [syscall](https://pkg.go.dev/syscall) (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) ## Dependencies diff --git a/c/bitcast/_cast/cast.c b/c/bitcast/_cast/cast.c new file mode 100644 index 000000000..bcc90d648 --- /dev/null +++ b/c/bitcast/_cast/cast.c @@ -0,0 +1,17 @@ +typedef union { + double d; + float f; + long v; +} castUnion; + +double llgoToFloat64(long v) { + castUnion k; + k.v = v; + return k.d; +} + +float llgoToFloat32(long v) { + castUnion k; + k.v = v; + return k.f; +} diff --git a/c/bitcast/bitcast.go b/c/bitcast/bitcast.go new file mode 100644 index 000000000..f6d123518 --- /dev/null +++ b/c/bitcast/bitcast.go @@ -0,0 +1,30 @@ +/* + * 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 bitcast + +import _ "unsafe" + +const ( + LLGoFiles = "_cast/cast.c" + LLGoPackage = "link" +) + +//go:linkname ToFloat64 C.llgoToFloat64 +func ToFloat64(v uintptr) float64 + +//go:linkname ToFloat32 C.llgoToFloat32 +func ToFloat32(v uintptr) float32 diff --git a/c/bitcast/llgo_autogen.lla b/c/bitcast/llgo_autogen.lla new file mode 100644 index 000000000..e495204ad Binary files /dev/null and b/c/bitcast/llgo_autogen.lla differ diff --git a/internal/lib/sync/atomic/atomic.go b/internal/lib/sync/atomic/atomic.go index 11bef422a..8d7bc8a38 100644 --- a/internal/lib/sync/atomic/atomic.go +++ b/internal/lib/sync/atomic/atomic.go @@ -16,7 +16,6 @@ package atomic -// llgo:skipall import ( "unsafe" ) diff --git a/internal/runtime/z_rt.go b/internal/runtime/z_rt.go index 9d9eea339..6653ff3d0 100644 --- a/internal/runtime/z_rt.go +++ b/internal/runtime/z_rt.go @@ -20,6 +20,7 @@ import ( "unsafe" "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/bitcast" "github.com/goplus/llgo/c/pthread" "github.com/goplus/llgo/internal/abi" ) @@ -58,7 +59,7 @@ func Panic(v any) { func Rethrow(link *Defer) { if ptr := excepKey.Get(); ptr != nil { if link == nil { - TracePanic(*(*Eface)(ptr)) + TracePanic(*(*any)(ptr)) c.Free(ptr) c.Exit(2) } else { @@ -77,14 +78,57 @@ func init() { // ----------------------------------------------------------------------------- +func unpackEface(i any) *eface { + return (*eface)(unsafe.Pointer(&i)) +} + // TracePanic prints panic message. -func TracePanic(v Eface) { - kind := v._type.Kind() - switch { - case kind == abi.String: - stringTracef(c.Stderr, c.Str("panic: %s\n"), *(*String)(v.data)) +func TracePanic(v any) { + print("panic: ") + switch e := v.(type) { + case nil: + println("nil") + return + case (interface{ Error() string }): + println(e.Error()) + return + case (interface{ String() string }): + println(e.String()) + return + } + e := unpackEface(v) + switch e.Kind() { + case abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Int64: + if isDirectIface(e._type) { + println(int64(uintptr(e.data))) + } else { + println(*(*int64)(e.data)) + } + case abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uint64, abi.Uintptr: + if isDirectIface(e._type) { + println(uint64(uintptr(e.data))) + } else { + println(*(*uint64)(e.data)) + } + case abi.Float32: + if isDirectIface(e._type) { + println(bitcast.ToFloat32((uintptr(e.data)))) + } else { + println(*(*float32)(e.data)) + } + case abi.Float64: + if isDirectIface(e._type) { + println(bitcast.ToFloat64(uintptr(e.data))) + } else { + println(*(*float64)(e.data)) + } + case abi.String: + println(*(*string)(e.data)) + default: + // TODO kind to e._type.Str_ + print("(", e.Kind(), ") ") + println(e.data) } - // TODO(xsw): other message type } func stringTracef(fp c.FilePtr, format *c.Char, s String) {