| #pragma once |
| |
| /* |
| * Note that cond_break can only be portably used in the body of a breakable |
| * construct, whereas can_loop can be used anywhere. |
| */ |
| #ifdef __BPF_FEATURE_MAY_GOTO |
| #define can_loop \ |
| ({ __label__ l_break, l_continue; \ |
| bool ret = true; \ |
| asm volatile goto("may_goto %l[l_break]" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: ret = false; \ |
| l_continue:; \ |
| ret; \ |
| }) |
| |
| #define __cond_break(expr) \ |
| ({ __label__ l_break, l_continue; \ |
| asm volatile goto("may_goto %l[l_break]" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: expr; \ |
| l_continue:; \ |
| }) |
| #else |
| #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| #define can_loop \ |
| ({ __label__ l_break, l_continue; \ |
| bool ret = true; \ |
| asm volatile goto("1:.byte 0xe5; \ |
| .byte 0; \ |
| .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \ |
| .short 0" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: ret = false; \ |
| l_continue:; \ |
| ret; \ |
| }) |
| |
| #define __cond_break(expr) \ |
| ({ __label__ l_break, l_continue; \ |
| asm volatile goto("1:.byte 0xe5; \ |
| .byte 0; \ |
| .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \ |
| .short 0" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: expr; \ |
| l_continue:; \ |
| }) |
| #else |
| #define can_loop \ |
| ({ __label__ l_break, l_continue; \ |
| bool ret = true; \ |
| asm volatile goto("1:.byte 0xe5; \ |
| .byte 0; \ |
| .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16; \ |
| .short 0" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: ret = false; \ |
| l_continue:; \ |
| ret; \ |
| }) |
| |
| #define __cond_break(expr) \ |
| ({ __label__ l_break, l_continue; \ |
| asm volatile goto("1:.byte 0xe5; \ |
| .byte 0; \ |
| .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16; \ |
| .short 0" \ |
| :::: l_break); \ |
| goto l_continue; \ |
| l_break: expr; \ |
| l_continue:; \ |
| }) |
| #endif |
| #endif |
| |
| #define cond_break __cond_break(break) |
| #define cond_break_label(label) __cond_break(goto label) |