diff --git a/c/bitcast/_cast/cast.c b/c/bitcast/_cast/cast.c new file mode 100644 index 000000000..01e34b2c3 --- /dev/null +++ b/c/bitcast/_cast/cast.c @@ -0,0 +1,17 @@ +typedef union { + double d; + float f; + long v; +} castUnion; + +double bitcastToFloat64(long v) { + castUnion k; + k.v = v; + return k.d; +} + +float bitcastToFloat32(long v) { + castUnion k; + k.v = v; + return k.f; +} \ No newline at end of file diff --git a/c/bitcast/bitcast.go b/c/bitcast/bitcast.go new file mode 100644 index 000000000..a0a7b6f51 --- /dev/null +++ b/c/bitcast/bitcast.go @@ -0,0 +1,14 @@ +package bitcast + +import _ "unsafe" + +const ( + LLGoFiles = "_cast/cast.c" + LLGoPackage = "link" +) + +//go:linkname ToFloat64 C.bitcastToFloat64 +func ToFloat64(v uintptr) float64 + +//go:linkname ToFloat32 C.bitcastToFloat32 +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/runtime/z_rt.go b/internal/runtime/z_rt.go index 9d9eea339..16a8f76ad 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,60 @@ func init() { // ----------------------------------------------------------------------------- +func unpackEface(i any) *eface { + return (*eface)(unsafe.Pointer(&i)) +} + +var ( + tyError = unpackEface((*interface{ Error() string })(nil))._type.Elem() +) + // 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 + println("(", e.Kind(), ")", e.data) } - // TODO(xsw): other message type } func stringTracef(fp c.FilePtr, format *c.Char, s String) {