gcc / clang:如何强制对堆栈中的项目进行排序?

时间:2015-09-01 19:51:16

标签: gcc clang inline

请考虑以下代码:

int a;
int b;

有没有办法强制堆栈前面的b?

进行排序的一种方法是将b放在函数中:

void foo() {
    int b;
}
...
int a;
foo();

但是,只有在没有内联的情况下,这通常才有效。

也许有不同的方法可以做到这一点?在两个声明之间放置一个内联汇编程序可能会有所帮助,但我不确定。

3 个答案:

答案 0 :(得分:1)

您最初的问题是强制函数调用不被内联。

要改进Jordy Baylac的答案,您可能会尝试在调用它的块中声明该函数,并且可能使用statement expr

#define FOO_WITHOUT_INLINING(c,i) ({ \
  extern int foo (char, int) __attribute__((noinline)); \
  int r = foo(c,i); \
  r; })

(如果foo的类型未知,您可以使用typeof

然而,我仍然认为你的问题制定得很糟糕(并且如果一个人避免阅读你的评论应该真正进入问题,这应该提到你的libmill)是没有意义的。根据{{​​3}}的定义,编译器可以根据需要内联任何函数,而无需更改程序的语义。

例如,您的库的用户可以使用-flto -O2合法地编译它(在编译和链接阶段)。我不知道那会发生什么。

我相信您可能会使用-fsplit-stack重新设计代码;你在C中实现了一些inlining吗?然后查看它的众多现有实现,以及call/cc内部....另请参阅Gabriel Kerneis CPC& setcontext(3)

也许您可能需要在GCC的return_twice(和/或nothrowlongjmp(3)或某些_Pragma function attribute

然后你编辑了你的问题以完全改变它(询问调用堆栈中变量的顺序),仍未提及问题中的 你的GCC optimize及其go宏(如你所愿;评论是不稳定的,因此不应包含大部分问题)。

但是C编译器甚至不应该在编译的程序中有一个调用堆栈(一个假设的C99符合编译器可以完成整个程序优化以避免任何调用堆栈)。并且GCC肯定允许在调用堆栈之外放置一些变量(例如,在寄存器中)并且它正在这样做。一些实现(可能libmill)有两个调用堆栈。

所以你改变的问题完全没有意义:变量可能不在堆栈中(例如,只有在寄存器中,或者如果编译器可以证明它在其他一些优化之后无用之后甚至完全消失),并且允许编译器为两个变量优化和使用相同的调用堆栈槽(GCC经常进行这样的优化)。所以你不能强制调用堆栈布局上的任何顺序。

如果您需要确定两个局部变量a& b在调用堆栈上有一些定义良好的顺序,将它们变成struct,例如。

struct { int _a, _b; } _locals;
#define a _locals._a
#define b _locals._b

然后,请务必将&_locals置于某处(例如,在volatile全局或线程局部变量中)。由于某些版本的GCC(IIRC 4.8或4.7)有一些优化过程来重新排序非转义字段struct - s

顺便说一句,您可以使用IA64扩展程序自定义GCC以帮助解决此问题(例如,介绍您自己的内置程序或编译指示执行部分工作)。

显然,你正在发明一些新的方言C(àlaMELT);那你应该这么说!

答案 1 :(得分:0)

below there is a way, using gcc attributes:

  char foo (char, int) __attribute__ ((noinline));

and, as i said, you can try -fno-inline-functions option, but this is for all functions in the compilation process

答案 2 :(得分:0)

我仍然不清楚为什么你希望函数不是内联函数,但这里是我提议的非专业解决方案:

您可以在单独的对象something.o文件中创建此功能。

由于您只包含标题,因此编译器无法内联函数。

然而,链接器可能决定稍后在链接时将其内联。