【发布时间】:2012-02-06 06:13:01
【问题描述】:
有什么方法可以让我在 C 中自动发现变量的类型,或者通过程序本身的某种机制,或者——更有可能——通过使用编译器传递到它在哪里解析变量并为其分配类型?我正在寻找有关此的一般建议。下面是关于我需要什么以及为什么需要的更多背景信息。
我想更改 OpenMP 缩减子句的语义。此时,似乎最简单的方法是简单地将源代码中的子句(通过脚本)替换为对函数的调用,然后我可以定义函数来实现我想要的归约语义。例如,我的脚本会转换这个
#pragma omp parallel for reduction(+:x)
进入这个:
my_reduction(PLUS, &x, sizeof(x));
#pragma omp parallel for
在哪里,早些时候,我有(比方说)
enum reduction_op {PLUS, MINUS, TIMES, AND,
OR, BIT_AND, BIT_OR, BIT_XOR, /* ... */};
并且my_reduction 有签名
void my_reduction(enum reduction_op op, void * var, size_t size);
除其他外,my_reduction 必须按照程序员最初的意图将加法运算应用于归约变量。但是我的函数不知道如何正确地做到这一点。特别是,虽然它知道操作的种类(PLUS)、原始变量的位置(var)以及变量类型的大小,但它并不知道变量本身的类型。特别是,它不知道var 是整数类型还是浮点类型。从低层次的 POV 来看,这两类类型的加法运算是完全不同的。
如果 GCC 支持的非标准运算符 typeof 能够按照 sizeof 的工作方式工作——返回某种类型的变量——我可以轻松解决这个问题。但 typeof 并不像 sizeof:显然,它只能在左值声明中使用。
现在,编译器显然在生成可执行代码之前确实知道 x 的类型。这让我想知道我是否可以以某种方式利用 GCC 的解析器,只是为了获取 x 的类型并将其传递给我的脚本,然后再次运行 GCC,以编译我更改的源代码。那么声明就很简单了
enum var_type { INT8, UINT8, INT16, UINT16, /* ,..., */ FLOAT, DOUBLE};
void my_reduction(enum reduction_op op, void * var, enum var_type vtype);
并且my_reduction 可以在取消引用和应用运算符之前进行适当的转换。
如您所见,我试图在 C 中创建一种“调度”机制。为什么不直接使用 C++ 重载呢?因为我的项目限制我使用用 C 编写的遗留源代码。我可以使用脚本自动更改代码,但无法将其重写为其他语言。
谢谢!
【问题讨论】:
-
如何使用一些工具/脚本对源代码进行后处理?例如。用 clang 解析它,找到类型,插入/调整特定类型的代码,编译?
-
谢谢,亚历克斯。听起来它正朝着正确的方向发展。
-
我在某处读到用户定义的缩减将成为 3.1 或 4.0 标准的一部分。嗯 3.1 说:
reduction({operator|intrinsic_procedure_name}:list)..从未尝试过内在程序名称。尽管它只部分解决了您的类型检测。 -
非虚拟机。
intrinsic_procedure_name指的是别的东西。