gnu cc扩展和ABI
gnc cc扩展标准c的语法,非常强大!!!详情请见:
http://uw714doc.sco.com/cgi-bin/info2html?%28gcc.info%29C%2520Extensions&lang=en
http://tigcc.ticalc.org/doc/gnuexts.html#SEC104
https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/C-Extensions.html#C-Extensions
ABI是application binary interface的缩写,规定了struct布局,函数调用规则,数据大小等。
非常值得研究。
比如:x86-64下,rbx,rbp,r12-r15是called saved registers。
参考文献:http://www.x86-64.org/documentation/abi.pdf
people.freebsd.org/~obrien/amd64-elf-abi.pdf
#define my_min(x, y) ({const typeof(x) __x = x; \
const typeof(y) __y = y; \
(void) (&__x == &__y); \
__x < __y ? __x : __y;})
struct Str
{
int a;
char b;
short c;
} __attribute__((packed));
#define ERR_PRINTF(fmt, args...) {\
char msg[1024]; \
snprintf(msg, sizeof(msg), "%s:%d "fmt"\n", __FUNCTION__, __LINE__, ##args);\
printf("%s", msg); \
}
#define ERR_PRINTF2(fmt, ...) \
printf("%s:%d "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
__attribute__ ((noinline)) bool CAS_64b(uint64_t* ptr, uint32_t* oldv, uint32_t* newv)
{
bool ret = false;
__asm__ __volatile__ (
"pushl %%ebx;"
"movl %4, %%ebx;"
"lock cmpxchg8b %1;\n"
"sete %0;\n"
"popl %%ebx;\n"
:"=m"(ret),"+m"(*(uint64_t volatile*)(ptr))
:"a"(oldv[0]), "d"(oldv[1]), "D"(newv[0]), "c"(newv[1])
:"memory");
return ret;
}
//#if defined(__x86_64__)
//#define CAS(ptr, oldv, newv) __sync_bool_compare_and_swap((uint64_t*)(ptr), *(uint64_t*)(&oldv), *(uint64_t*)(&newv))
//#else
#define CAS(ptr, oldv, newv) CAS_64b((uint64_t*)(ptr), (uint32_t*)(&oldv), (uint32_t*)(&newv))
//#endif
struct A
{
int a;
int b;
};
void test_CAS()
{
struct A sa = {1, 2};
struct A sb = {3, 4};
struct A sc = sa;
if(CAS(&sc, sa, sb))
printf("success, %d %d\n", sb.a, sb.b) ;
else
printf("fail, %d %d\n", sb.a, sb.b);
}
void f_unlikely()
{
printf("go unlikely\n");
}
void f_likely()
{
printf("go likely\n");
}
void test_aligned(char* p)
{
char* q = (char*)((((size_t)p + 3)>>2)<<2);
*((int*)(q+1)) = 3;
}
void test_likely(int x)
{
if(unlikely(x))
f_unlikely();
else
f_likely();
}
void test_return_addr()
{
void* p = __builtin_return_address(0);
printf("address \t %p\n", p);
}
void test_frame_addr()
{
void* p = __builtin_frame_address(0);
printf("address \t %p\n", p);
}
int main()
{
//typeof
//statement expression
int c = my_min(1, 2);
printf("%d\n", c);
//packed
printf("sizeof(Str) = %u\n", (uint32_t)sizeof(Str));
//##
ERR_PRINTF("%d test", 1);
ERR_PRINTF("test2");
ERR_PRINTF2("%d test", 1);
//printf("%s:%d ""test2""\n", __FUNCTION__, 80, ); // the , still exists
ERR_PRINTF2("test2");
//__builtin_expect
test_likely(1);
//__builtin_return_address
test_return_addr();
//__builtin_frame_address
test_frame_addr();
//test aligned
char pp[11] = {0};
test_aligned(pp);
//test CAS
test_CAS();
while(1)
sleep(10);
return 0;
}
执行结果:
[ ~/code/test_sighup]$ ./test_gcc_ex
1
sizeof(Str) = 7
main:120 1 test
main:121 test2
main:123 1 test
main:125 test2
go unlikely
address 0x804882b
address 0xffb33aa8
success, 3 4
objdump -DC ./test_gcc_ex
00000000004006a0 <test_likely(int)>:
4006a0: 85 ff test %edi,%edi
4006a2: 75 05 jne 4006a9 <test_likely(int)+0x9>
4006a4: e9 d7 ff ff ff jmpq 400680 <f_likely()>
4006a9: e9 e2 ff ff ff jmpq 400690 <f_unlikely()>
4006ae: 66 90 xchg %ax,%ax
参考代码:
http://blog.csdn.net/cugxueyu/article/details/1955372
浙公网安备 33010602011771号