-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Forward declared Phi instructions - with dodgy workaround ;) #89
Comments
Gah, ignore this. After coming back to it, the problem was obvious:
should be:
Oops. 😉 |
The reason that this fails is that Unfortunately. solving these kind of circular reference cases is tricky. I would probably do something along the lines of: entryBlk := x.NewBlock("entry")
// ...
forLoopBlk := x.NewBlock("entry")
forBodyBlk := x.NewBlock("entry")
val6 := forBodyBlk.NewAdd(nil, constant.NewInt(types.I32, 1)) // <<<--- notice that we use nil as a dummy value here.
val2 := forLoopBlk.NewPhi(ir.NewIncoming(i32zero, entryBlk), ir.NewIncoming(val6, forBodyBlk))
val6.X = val2 // <<--- and set the actual value of val6.X here.
// ... |
That would solve the first panic, but, the value would be the wrong one. Since you would effectively and up with the different So, as we would say in Swedish "Håll tungan rätt i munnen" when working with circular references in data structures. ;) The translation of which for those not native in Swedish would be along the lines of Keep the tongue straight in the mouth, for added precision. |
Oh, and a quick tip. When you get panics like the following:
An easy way to find the line number causing the crash is by simply replacing -fmt.Println(m) // produces `PANIC=String method: runtime error: invalid memory address or nil pointer dereference` message, but no stack trace.
+m.String() // produces stack trace with source file name and line numbers. |
Yeah, it moves things out of order though, so kills readability. 😦
The easy workaround for that was to just set it directly, as I know in advance the value it needs to be:
Cheating? Yep. In cases where the value isn't known in advance though, such as generating new LLVM IR instead of trying to match existing IR... the correct approach you gave above would probably be better. 😄 |
Thanks, just tried it and that helps heaps. 😄 |
Hehe, yeah. That approach works for producing LLVM IR assembly :p However, if you want to use the in-memory representation of the IR, the value should really be one and the same (as in the same pointer). Otherwise, data flow analysis is going to get quite messed up. In the future, we will start working on control flow and data flow analysis packages (see #19, note that this is an old issue, and the API is not likely to stay as proposed), and given a function e.g. |
Stumbled on an interesting case with Phi instructions, and figured out a dodgy workaround that is probably good enough for now.
Hoping there's a better way, just in case. 😄
Scenario: attempting to generate some LLVM IR with the following structure:
Note that
%2
is referenced by the%6
creation line, and the%6
is referenced by the%2
creation line.It seems like just declaring the Go container for
%6
before it's called would work:Indeed, this compiles.
However,
fmt.Println()
on the module fails:After some investigation, the problem turned out to be the
String()
method here:llvm/ir/inst_other.go
Line 224 in c5c443d
It assumes the Phi Incoming has already had it's contents set, thus barfing when that's not the case (like above). In the above case, X is still
nil
at this point. 😉The dodgy workaround was to add some bogus contents to the variable (without adding them to the block), so
String()
works on it ok. eg:Is there a better approach? 😄
The text was updated successfully, but these errors were encountered: