#ifndef PICKNO # define PICKNO 1 #endif #if PICKNO == 2 # define PICK(fn1, fn2) #fn2 #else # define PICK(fn1, fn2) #fn1 #endif #ifdef __x86_64__ # define IFUNC_ASM(fn) "\tleaq " fn "(%rip), %rax\n\tretq\n" #endif #define IFUNC(name, globl, fn1, fn2) \ extern __typeof (fn1) fn1 __attribute__((used)); \ extern __typeof (fn2) fn2 __attribute__((used)); \ extern __typeof (fn1) name; \ asm (globl " " #name "\n" \ "\t.type " #name ", @gnu_indirect_function\n" \ #name ":\n" \ IFUNC_ASM (PICK (fn1, fn2)) \ "\t.size " #name ", .-" #name "\n") #define IFUNC_LOCAL(name, fn1, fn2) IFUNC(name, ".local", fn1, fn2) #define IFUNC_GLOBAL(name, fn1, fn2) IFUNC(name, ".globl", fn1, fn2) static int foo1 (void) { return 1; } static int foo2 (void) { return 2; } IFUNC_LOCAL (foo, foo1, foo2); extern void abort (void); int main (void) { if (foo () != PICKNO) abort (); return 0; }