Right now gcc does not officially support local control flow of any kind. The user is free to jump around within an asm block using local labels but this is cumbersome and bug-prone. Jumping out of an asm block in any way is (un?)officially verboten.
This RFE is for support of jumping from an asm block to a label defined somewhere in the enclosing function. It does not deal with jumps between asm blocks or non-local control flow like function calls (both of which are understandably nasty). Rationale: 1. There is demand for this feature. MSVC supports it (see http://msdn.microsoft.com/en-us/library/aa279405(VS.60).aspx), and people currently kludge it in gcc by defining assembler labels in other asm blocks and jumping to them, even though the gcc docs explicitly forbid it (e.g. http://stackoverflow.com/questions/744055/gcc-inline-assembly-jump-to-label-outside-block). Jumping to a C label is less error-prone, more general, and significantly easier to implement than asm-asm jumps (see #4). 2. It's already implemented. The assembler label corresponding to a C label is accessible like this -- asm("jmp %l0" ::"i"(&&label)) -- where "%l" emits the label "with the syntax expected of a jump target" (Brennan's inline asm guide). All that's left is for the compiler to mark such labels as used-by-computed-goto so the optimizer plays nice; even that can be faked with judicious use of computed gotos (see example code, below). 3. Its effect is basically the same as for a computed goto, which is already supported. I suspect that every argument that jumping from asm to C is inherently unsafe or difficult to implement applies equally well to computed gotos (e.g. Bug #37722). 4. It would encourage smaller asm blocks because internal control flow would seldom be necessary any more. The resulting code would be easier to write and debug, more portable, and less fragile. Further, the example below suggests that the compiler may generate better code as well. Example: Efficient use of condition codes Currently the only way to use condition codes generated within an asm block is to either convert them to an output value (which requires extra instructions to create and test) or to embed the if/else inside the asm block (forcing the user to write extra assembly code even if it was otherwise portable). Support for jumping from asm to local labels would allow a better idiom: void handle_overflow(int a, int b, int* dest); int ideal_foo(int a, int b) { int rval = a; asm("adc %[src], %[dest]\n\t" "jno %l[no_overflow]" : [dest] "+r"(rval) : [src] "r"(b), [no_overflow] "i"(&&done)); handle_overflow(a, b, &rval); done: return rval; } int current_foo(int a, int b) { int overflow = 0; int rval = a; asm("adc %[src], %[dest]\n\t" "cmovo %[true], %[overflow]" : [dest] "+r"(rval), [overflow] "+r"(overflow) : [src] "r"(b), [true] "r"(1)); if(overflow) handle_overflow(a, b, &rval); return rval; } int hacked_foo(int a, int b) { static void* volatile labels[] = {&&overflow, &&no_overflow}; int rval=a; asm("adc %[src], %[dest]\n\t" "jno %l[no_overflow]\n\t" "jmp %l[overflow]" : [dest] "=r"(rval) : [src] "r"(b), "[dest]"(rval), [no_overflow] "i"(&&no_overflow), [overflow] "i"( &&overflow)); goto *labels[0]; overflow: handle_overflow(a, b, &rval); no_overflow: return rval; } Extracts of x86_64 assembler output for "x86_64-unknown-linux-gnu-gcc-4.2.2 -S -O3" follows. Notice that ideal_foo is clearly the best, *except* that the optimizer broke it by moving .L9 to the top of the loop (it should be just above the addq). If it were optimized better it would take only four instructions on the short path. hacked_foo would also beat current_foo by quite a bit, except the compiler decided to set up a stack frame for it: ideal_foo: .L9: subq $16, %rsp movl %edi, %eax leaq 12(%rsp), %rdx movl %edi, 12(%rsp) #APP adc %esi, %eax jno .L9 #NO_APP movl %eax, 12(%rsp) call handle_overflow movl 12(%rsp), %eax addq $16, %rsp ret current_foo: pushq %rbx xorl %eax, %eax movl $1, %edx movl %eax, %ebx movl %edi, %ecx subq $16, %rsp #APP adc %esi, %ecx cmovo %edx, %ebx #NO_APP testl %ebx, %ebx movl %edi, 12(%rsp) movl %ecx, %eax movl %ecx, 12(%rsp) je .L12 leaq 12(%rsp), %rdx call handle_overflow movl 12(%rsp), %eax .L12: addq $16, %rsp popq %rbx ret hacked_foo: movq %rbx, -16(%rsp) movq %rbp, -8(%rsp) subq $32, %rsp movl %edi, 12(%rsp) movl %edi, %eax #APP adc %esi, %eax jno .L4 jmp .L5 #NO_APP movl %eax, 12(%rsp) movq labels.1894(%rip), %rax jmp *%rax .p2align 4,,7 .L5: leaq 12(%rsp), %rdx call handle_overflow .L4: movl 12(%rsp), %eax movq 16(%rsp), %rbx movq 24(%rsp), %rbp addq $32, %rsp ret -- Summary: Inline asm should support limited control flow Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: inline-asm AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: scovich at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40124