1 #pragma once 2 3 /* 4 * Note that cond_break can only be portably used in the body of a breakable 5 * construct, whereas can_loop can be used anywhere. 6 */ 7 #ifdef __BPF_FEATURE_MAY_GOTO 8 #define can_loop \ 9 ({ __label__ l_break, l_continue; \ 10 bool ret = true; \ 11 asm volatile goto("may_goto %l[l_break]" \ 12 :::: l_break); \ 13 goto l_continue; \ 14 l_break: ret = false; \ 15 l_continue:; \ 16 ret; \ 17 }) 18 19 #define __cond_break(expr) \ 20 ({ __label__ l_break, l_continue; \ 21 asm volatile goto("may_goto %l[l_break]" \ 22 :::: l_break); \ 23 goto l_continue; \ 24 l_break: expr; \ 25 l_continue:; \ 26 }) 27 #else 28 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 29 #define can_loop \ 30 ({ __label__ l_break, l_continue; \ 31 bool ret = true; \ 32 asm volatile goto("1:.byte 0xe5; \ 33 .byte 0; \ 34 .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \ 35 .short 0" \ 36 :::: l_break); \ 37 goto l_continue; \ 38 l_break: ret = false; \ 39 l_continue:; \ 40 ret; \ 41 }) 42 43 #define __cond_break(expr) \ 44 ({ __label__ l_break, l_continue; \ 45 asm volatile goto("1:.byte 0xe5; \ 46 .byte 0; \ 47 .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \ 48 .short 0" \ 49 :::: l_break); \ 50 goto l_continue; \ 51 l_break: expr; \ 52 l_continue:; \ 53 }) 54 #else 55 #define can_loop \ 56 ({ __label__ l_break, l_continue; \ 57 bool ret = true; \ 58 asm volatile goto("1:.byte 0xe5; \ 59 .byte 0; \ 60 .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16; \ 61 .short 0" \ 62 :::: l_break); \ 63 goto l_continue; \ 64 l_break: ret = false; \ 65 l_continue:; \ 66 ret; \ 67 }) 68 69 #define __cond_break(expr) \ 70 ({ __label__ l_break, l_continue; \ 71 asm volatile goto("1:.byte 0xe5; \ 72 .byte 0; \ 73 .long (((%l[l_break] - 1b - 8) / 8) & 0xffff) << 16; \ 74 .short 0" \ 75 :::: l_break); \ 76 goto l_continue; \ 77 l_break: expr; \ 78 l_continue:; \ 79 }) 80 #endif 81 #endif 82 83 #define cond_break __cond_break(break) 84 #define cond_break_label(label) __cond_break(goto label) 85