elliotchance / c2go

⚖️ A tool for transpiling C to Go.
MIT License
2.07k stars 154 forks source link

panic: invalid identity: #785

Open jcburley opened 6 years ago

jcburley commented 6 years ago

Attempting to transpile https://github.com/jcburley/LispZero/blob/master/lisp-zero.c, I get this:

$ c2go transpile lisp-zero.c
panic: invalid identity: 'BSstructSatSShomeScraigSgithubSLispZeroSlispTzeroPcD329D9E *'

goroutine 1 [running]:
github.com/elliotchance/c2go/util.NewIdent(0xc4208447d7, 0x3c, 0xc420844a50)
    /home/craig/.go/src/github.com/elliotchance/c2go/util/goast.go:231 +0xa7d
github.com/elliotchance/c2go/transpiler.transpileRecordDecl(0xc4201e8120, 0xc42023ee70, 0xc420a653a0, 0xc4201e8120, 0x6c5e00, 0xc42023ee70, 0x4cbea8)
    /home/craig/.go/src/github.com/elliotchance/c2go/transpiler/declarations.go:242 +0x1914
github.com/elliotchance/c2go/transpiler.transpileToNode(0x6c5e00, 0xc42023ee70, 0xc4201e8120, 0x0, 0x0, 0x0, 0x0, 0x0)
    /home/craig/.go/src/github.com/elliotchance/c2go/transpiler/transpiler.go:463 +0x250
github.com/elliotchance/c2go/transpiler.transpileTranslationUnitDecl(0xc4201e8120, 0xc42039a640, 0xc4201a8000, 0x11d, 0x200, 0x0, 0x0)
    /home/craig/.go/src/github.com/elliotchance/c2go/transpiler/translation_unit.go:116 +0x184
github.com/elliotchance/c2go/transpiler.transpileToNode(0x6c6080, 0xc42039a640, 0xc4201e8120, 0x0, 0x0, 0x0, 0x0, 0x0)
    /home/craig/.go/src/github.com/elliotchance/c2go/transpiler/transpiler.go:440 +0xaf1
github.com/elliotchance/c2go/transpiler.TranspileAST(0x0, 0x0, 0x68dfad, 0x4, 0xc4201e8120, 0x6c6080, 0xc42039a640, 0x0, 0x2c000)
    /home/craig/.go/src/github.com/elliotchance/c2go/transpiler/transpiler.go:32 +0x1f5
main.Start(0x0, 0xc420096080, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68dfad, ...)
    /home/craig/.go/src/github.com/elliotchance/c2go/main.go:301 +0xf53
main.runCommand(0xc42008e058)
    /home/craig/.go/src/github.com/elliotchance/c2go/main.go:433 +0x484
main.main()
    /home/craig/.go/src/github.com/elliotchance/c2go/main.go:356 +0x22
jcburley commented 6 years ago

A little debugging later and I found this workaround helps c2go run to completion:

https://github.com/jcburley/LispZero/commit/283d015ead46ea3f6df890b63bbd7a81fec6c22d

(I'm new to Go, dlv, etc., so it took me a little while to find my feet -- but let me know if you want me to try to find and fix the bug, which I gather is a case of the conversion of an unnamed/anonymous struct not working.)

elliotchance commented 6 years ago

I believe @Konstantin8105 worked mostly on getting the typedef and struct parts working c2go, so I don't immediately know why the panic is happening.

if you are able to debug and fix the issue that would be amazing. 😄

Konstantin8105 commented 6 years ago

Dear @jcburley, please try another tool c4go.

jcburley commented 6 years ago

c4go does not crash on this tiny test case:

typedef struct {
  int a;
  int b;
} *twoints;

(c2go currently does.)

c4go generates this from that test case:

//
//  Package main - transpiled by c4go
//
//  If you have found any issues, please raise an issue at:
//  https://github.com/Konstantin8105/c4go/
//

package main

type __struct_at__home_craig__go_src_github_com_jcburley_lisp_zero_c4go_anon_struct_c_1_9_ struct {
    a int
    b int
}
type twoints []__struct_at__home_craig__go_src_github_com_jcburley_lisp_zero_c4go_anon_struct_c_1_9_

func init() {
}

That looks correct to me, and go build anon-struct.go complains only about undefined main.main.

My other tiny test cases (posted in other Issues) show no real improvement, though some changes.

Also, c4go is unable to generate a go-buildable version of the current lisp-zero-single.c, as the following diagnostics are produced:

$ go build lisp-zero-single.go
# command-line-arguments
./lisp-zero-single.go:376:42: syntax error: unexpected =, expecting )
./lisp-zero-single.go:653:124: syntax error: unexpected =, expecting )
./lisp-zero-single.go:1375:126: syntax error: unexpected =, expecting )
$

E.g. the first line (376) complained about is:

    if iter[0].node == nil || (iter[0].node = iter[0].node[0].next) == nil {

Whereas the c2go version of that same (.c) line reads:

    if (*iter).node == nil || (func() *map_node_t {
        (*iter).node = (*(*iter).node).next
        return (*iter).node
    }()) == nil {

Let me know if you need more information on that, and how best I could provide it, but you might be expecting those sorts of problems given the state of your fork (its baseline, etc).

Konstantin8105 commented 6 years ago

Dear @jcburley May be error on (376) is possible to solve.

const char *map_next_(map_base_t *m, map_iter_t *iter) {
  if (!iter->node || !(iter->node = iter->node->next)) {
//                          ======================

FYI: Golang is not C. Some of C syntax is fundamental impossible to transpile to Go. Some corner cases is not solver in transpilers(like you found). Some of them you can see in issues of that projects.

jcburley commented 6 years ago

Do you think the c2go transpilation of the same code (shown above) is wrong, even though it compiles and seems to run okay?

(It looks okay to me, but I'm no Go expert, having started to really look at Go code only yesterday!)

jcburley commented 6 years ago

(Did you mean "May be error on (376) is impossible to solve, by the way?)

Konstantin8105 commented 6 years ago

Both projects c2go, c4go doing maximum for creating valid Go code.

  1. At the begin of result Go code, you can see transpilation warnings:

    // Warning (*ast.EnumDecl):  /usr/include/ctype.h:46 :Add support of continues counter for type : *ast.BinaryExpr
    // Warning (*ast.MemberExpr):  $GOPATH/src/templorary/LispZero/lisp-zero-single.c:140 :cannot determine type for LHS 'map_node_t *', will use 'void *' for all fields. Is lvalue = true. n.Name = hash
    // Warning (*ast.MemberExpr):  $GOPATH/src/templorary/LispZero/lisp-zero-single.c:141 :cannot determine type for LHS 'map_node_t *', will use 'void *' for all fields. Is lvalue = true. n.Name = value

    Usually it is mean transpilation is wrong, but sometimes it is mean nothing.

  2. Result Go code can use package unsafe, usually it is ok:

    import "unsafe"

    But if you have access to memory with more 1Gb, then your code is panic.

    node[0].value = (*(*[1000000000]byte)(unsafe.Pointer(uintptr(unsafe.Pointer
    //                  ================= 

Also, using package unsafe is not Go-way and the best way avoid this package.


Error on (376) is possible to solve at the future.

jcburley commented 6 years ago

Hm, I don't see those warnings at the top of my (current) lisp-zero-single.go file.

I have other tests that allocate VMpeak as high as 3.8G yet seem to run to completion just fine. (These are performance tests, as I'm trying to get a handle on Go versus C code for the application I have in mind.)

Anyway, my lisp-zero-single.c code is definitely written to a lower level of C than I expect "proper" Go code to be. I'm going to look into converting it into a "proper" Go program (leveraging the automatic conversions done by c2go, but doing the rest by hand) as my next step. I've run out of time on the pure auto-conversion side of things (for now anyway), but hope the project continues to progress!