# Goto and Compile to C

When I use Goto inside compile and use CompilationTarget->"C" I get error message:

fun = Compile[{},
Goto["here"];
Label["here"];
, CompilationTarget -> "C"]


or

fun2 = Compile[{{myt, _Real}, {i, _Integer}},
Module[{t = myt},
Do[If[j >= i, Goto["one"], Goto["two"]];
Label["one"];
t = j;
Break[];
Label["two"];, {j, 1, 10}];
t
], CompilationTarget -> "C"

]


SymbolicCToCCodeString::unk: An unknown element, CCodeGeneratorPrivatebuildLine[10,CCodeGeneratorPrivateobjData\$1791,CompiledFunctionToolsPrivategetInstruction[10,{0,one}]], was found when generating code >>

CCompilerDriverCreateLibrary::cmperr: Compile error: C:\Users\myusername\AppData\Roaming\Mathematica\ApplicationData\CCompilerDriver\BuildFolder\d985623-6852\Working-number-6852-6272-1\compiledFunction0.c(104) : error C2065: 'CUnknownElement' : undeclared identifier >>

Without compiling to C it works well.

• Maybe it doesn't support goto. It should always be possible to rephrase a program without goto though. – Szabolcs Feb 11 '15 at 16:41
• here mathematica.stackexchange.com/questions/1096/… it says it is compilable. How can I for example rephrase fun2 without Goto? – MOON Feb 11 '15 at 16:43
• worth reiterating the issue is specific to the CompilationTarget->"C" option. Works fine for other (or no) target specified. For your example you can just put the code blocks inside the If. – george2079 Feb 11 '15 at 17:08
• @george2079 It works when I put the code block inside If. Thank you. – MOON Feb 11 '15 at 17:22
• @yashar Yes, it was clear from your question that it's compilable to byte code. I meant to say that that doesn't necessarily mean that it's compilable to C. You could ask Wolfram support about it though. – Szabolcs Feb 11 '15 at 18:00

Almost 3 years later.. The problem lies in the Label instruction. What happens when you have code that contains labels and gotos is that the Goto instructions are successfully converted to valid jump op-codes. The labels, however, are just, well, labels. They don't even have a meaning, because jumps in compiled code are converted to jumps to a line number. Therefore, they are turned into no-ops. this can be seen in this example:

fun = Compile[{{a, _Real, 0}},
Module[{x = 1., xp = 0., begin, end},
Label[begin];
If[Abs[xp - x] < 10^-8, Goto[end]];
xp = x;
x = (x + a/x)/2;
Goto[begin];
Label[end];
x]
]


Look at fun // InputForm and you will find {0, begin} which means op-code 0 for "nothing". When a C function is to be constructed from this compiled function, every op-code is converted into its C form. Like this:

<< CompiledFunctionTools
CompiledFunctionToolsPrivategetInstruction[0, {16, 0, 1}]

(* Instruction[Times, Register[Real, 1], {Register[Real, 0]}] *)


Unfortunately, it seems to be an oversight that exactly this is not implemented for the noop code. Since it cannot be turned into a valid instruction, the C-compiler will never get a valid instruction list. Look at the error

Can we fix this? Surely. The question is what is the next best instruction for a noop instruction? Well, jump to the next line sounds reasonable.

To understand why this works you have to know that jumps to labels are turned into jumps to line numbers. So we don't really need the labels at all at this stage anymore.

Unprotect[CompiledFunctionToolsPrivategetInstruction];
CompiledFunctionToolsPrivategetInstruction[line_, {0, _}] :=
CompiledFunctionToolsPrivategetInstruction[line, {3, 1}]


Instruction {3,1} is a jump (3) to the line: current line + 1.

fun = Compile[{{a, _Real, 0}},
Module[{x = 1., xp = 0., begin, end},
Label[begin];
If[Abs[xp - x] < 10^-8, Goto[end]];
xp = x;
x = (x + a/x)/2;
Goto[begin];
Label[end];
x], CompilationTarget -> "C"
]

fun[2]
(* 1.41421 *)
`