Clang 我可以更改参数计算的顺序吗?
Clang从左到右评估其参数,gcc从右到左评估其参数。(根据C和C++语言规范都可以),有没有办法改变CLAN中的参数评估顺序?如果不是通过pragma或编译器开关,也许有人可以给我指出代码库中正确的位置Clang 我可以更改参数计算的顺序吗?,clang,Clang,Clang从左到右评估其参数,gcc从右到左评估其参数。(根据C和C++语言规范都可以),有没有办法改变CLAN中的参数评估顺序?如果不是通过pragma或编译器开关,也许有人可以给我指出代码库中正确的位置 一些背景信息:我有一个巨大的(第三方,没有那么好的文档)代码库,我试图从gcc移植到clang,我发现了一些奇怪的问题。根据以前的经验,我认为问题的一部分是论证顺序的评估。能够在两种模式之间来回切换而不混合两个完全不同的编译器(因此可能会引入许多其他问题源)将非常有助于将问题一分为二。没有
一些背景信息:我有一个巨大的(第三方,没有那么好的文档)代码库,我试图从gcc移植到clang,我发现了一些奇怪的问题。根据以前的经验,我认为问题的一部分是论证顺序的评估。能够在两种模式之间来回切换而不混合两个完全不同的编译器(因此可能会引入许多其他问题源)将非常有助于将问题一分为二。没有任何选项或术语来颠倒函数参数求值的顺序。但是现有的代码支持MSVC ABI(它似乎需要从右到左的参数求值)。下面的hack(针对当前clang svn trunk的补丁)可用于根据环境变量
clang\u reverse\u ARGS
的值反转参数求值顺序。值1
反转顺序,值0
保持顺序不变
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp (revision 229661)
+++ lib/CodeGen/CGCall.cpp (working copy)
@@ -2676,9 +2676,20 @@
CallExpr::const_arg_iterator ArgEnd,
const FunctionDecl *CalleeDecl,
unsigned ParamsToSkip) {
+ bool ForceReverseArgs = false;
+ const char *p = getenv("CLANG_REVERSE_ARGS");
+ if (p != nullptr) {
+ if (!strcmp(p, "1"))
+ ForceReverseArgs = true;
+ else if (strcmp(p, "0")) {
+ fprintf(stderr, "Expected $CLANG_REVERSE_ARGS to be '0' or '1'!\n");
+ exit(1);
+ }
+ }
+
// We *have* to evaluate arguments from right to left in the MS C++ ABI,
// because arguments are destroyed left to right in the callee.
- if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee() || ForceReverseArgs) {
// Insert a stack save if we're going to need any inalloca args.
bool HasInAllocaArgs = false;
for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end();
索引:lib/CodeGen/CGCall.cpp
===================================================================
---lib/CodeGen/CGCall.cpp(修订版229661)
+++lib/CodeGen/CGCall.cpp(工作副本)
@@ -2676,9 +2676,20 @@
CallExpr::const_arg_迭代器ArgEnd,
常量函数decl*被调用的函数decl,
无符号参数(跳过){
+布尔力反向搜索=假;
+const char*p=getenv(“铿锵的声音”);
+如果(p!=nullptr){
+如果(!strcmp(p,“1”))
+ForceReverseArgs=真;
+否则如果(strcmp(p,“0”)){
+fprintf(stderr,“预期$CLANG_REVERSE_ARGS为'0'或'1'!\n”);
+出口(1);
+ }
+ }
+
//我们*在MS C++ +ABI中评估从右到左的参数,
//因为参数在被调用方中从左到右被销毁。
-if(CGM.getTarget().getCXXABI().AreaRGSDRestoroyedLeftToRightInCallee()){
+if(CGM.getTarget().getCXXABI().AreaRGSDRestoroyedLeftToRightInCallee()| | ForceReverseArgs){
//如果需要任何inalloca参数,请插入堆栈保存。
bool HasInAllocaArgs=假;
对于(ArrayRef::iterator I=ArgTypes.begin(),E=ArgTypes.end();
它甚至似乎起了作用:
$ cat > demo.c << EOT
#include <stdio.h>
int a() {
printf("a\n");
return 1;
}
int b() {
printf("b\n");
return 2;
}
int main() {
printf("%d%d\n", a(), b());
return 0;
}
EOT
$ CLANG_REVERSE_ARGS=0 Debug+Asserts/bin/clang demo.c && ./a.out
a
b
12
$ CLANG_REVERSE_ARGS=1 Debug+Asserts/bin/clang demo.c && ./a.out
b
a
12
$cat>demo.c我认为clang仍然从右向左评估参数
考虑以下代码:
intadd(inta,intb)
{
返回a+b;
}
在叮当声后编译时:
080483c0:
80483c0:55推力%ebp
80483c1:89 e5 mov%esp,%ebp
80483c3:83 ec 08子$0x8,%esp
80483c6:8b 45 0c mov 0xc(%ebp),%eax
80483c9:8b 4d 08 mov 0x8(%ebp),%ecx
80483cc:89 4d fc mov%ecx,-0x4(%ebp)
80483cf:89 45 f8 mov%eax,-0x8(%ebp)
80483d2:8b 45 fc mov-0x4(%ebp),%eax
80483d5:03 45 f8添加-0x8(%ebp),%eax
80483d8:83 c4 08添加$0x8,%esp
80483db:5d pop%ebp
80483dc:c3 ret
80483dd:0f 1f 00 nopl(%eax)
让我们考虑一下这段反编译代码:
mov将参数复制到堆栈中
`
+---------+
|高|
+---------+
|101 |堆栈上的参数顺序由ABI定义,与参数表达式的计算顺序无关 问题是关于后者,而不是前者。
+---------+
|high |
+---------+
|101 |<-arg2
+---------+
|99 |<-arg1
+---------+
|ret |
+---------+
|ebp |
+---------+
|99 |<-a
+---------+
|101 |<-b
+---------+
|low |
+---------+