如何判断函数参数是否是立即的?

时间:2012-11-29 08:57:25

标签: c gcc ld gas

我有一个包含内联汇编的内联函数定义。我想选择 根据是否参数的事实,不同的内联汇编实现 在构建时间内是否已知。

我的问题是如何在C代码或内联汇编中询问地址值是否在构建时是已知的,因此适合作为直接值。如果您正在考虑__builtin_constant_p - 请提前阅读。

以下是一些说明我意图的代码:我试图找到一种方法来实现“is_immediate”。

static char arr[5];

void __attribute__((always_inline)) do_something(char * buf)
{
   if(is_immediate(buf) {

        // Argument is constant, can use immediate form

        asm volatile ("insn1 %0" : : "i"(buf));

   } else {

        // Argument is computed at runtime, use a register

        unsigned long tmp = (unsigned long)buf + 1;

        asm volatile("insn2 %0" : : "r"(tmp));

}


int main(void) 
{
   do_something(&arr);
}

第一印象__builtin_constant_p()似乎正好需要魔法,除非它不起作用。

原因是不起作用的是,在链接器将数组放入内存并为其选择地址之后,将知道数组的地址(因此它确实符合内联汇编的直接约束),在链接之前的编译时间不知道。

所以,我正在寻找的是一种方式 - “这个变量是否适合作为直接值?”而不是“这是一个不变的表达吗?”。

1 个答案:

答案 0 :(得分:0)

如果我看看我的x86编译器生成的内容(这个insn毕竟没有意义),它就在这里:

static char arr[5];

void __attribute__((always_inline)) do_something(char * buf)
{

        // Argument is constant, can use immediate form

        asm volatile ("insn1 %0" : : "r"(buf));

        unsigned long tmp = (unsigned long)buf;

        asm volatile("insn2 %0" : : "r"(tmp));

}


int main(void)
{
   char brr[5];
   do_something(arr);
   do_something(brr);
}

        .file   "inl.c"
        .text
.globl do_something
        .type   do_something, @function
do_something:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        popl    %ebp
        ret
        .size   do_something, .-do_something
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    $arr, %eax
        movl    %esp, %ebp
        subl    $16, %esp
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        leal    -5(%ebp), %eax
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        leave
        ret
        .size   main, .-main
        .local  arr
        .comm   arr,5,4
        .ident  "GCC: (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]"
        .section        .comment.SUSE.OPTs,"MS",@progbits,1
        .string "OSpwg"
        .section        .note.GNU-stack,"",@progbits

所以我认为立即行动是有意义的,因为$arr可能是立即的(而leal -5(%ebp), %eax不是)。可能不支持所述优化。

但另一方面,

            movl    $arr, %eax
            insn1 %eax

并不比

差得多
            insn1 $arr

所以它仍然可以接受,恕我直言。