我可以更改 clang 中参数评估的顺序吗?

Cli*_*nna 5 clang

Clang 从左到右评估其参数,gcc 从右到左评估其参数。(根据 C 和 C++ 语言规范,两者都可以,另请参阅g++ vs intel/clang 参数传递顺序?)有没有办法改变 clang 中参数求值的顺序?如果不通过编译指示或编译器开关,也许有人可以指出我在 clang 代码库中的正确位置?


一些背景信息:我有一个巨大的(第三方,没有很好记录的)代码库,我试图将其从 gcc 移植到 clang,但我看到了奇怪的问题。根据以前的经验,我认为至少部分问题在于论证顺序评估。能够在两种模式之间来回切换而不混合两个完全不同的编译器(因此可能会引入许多其他问题来源)对于解决问题非常有帮助。

Cli*_*nna 4

clang 中没有选项或编译指示来反转函数参数求值的顺序。但是现有代码支持 MSVC ABI(似乎需要从右到左进行参数评估)。以下 hack(针对当前 clang svn trunk 的补丁)可用于根据环境变量的值反转参数评估的顺序 CLANG_REVERSE_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();
Run Code Online (Sandbox Code Playgroud)

它甚至似乎有效:

$ 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
Run Code Online (Sandbox Code Playgroud)

我已经构建了一个大型 C++ 项目,该项目在“弗兰肯斯坦模式”下有一个大型测试台:一半的对象CLANG_REVERSE_ARGS=1带有CLANG_REVERSE_ARGS=0. 生成的二进制文件通过了项目的测试平台。