怎么看降低c
我正在努力提高对C实际工作原理的理解.有没有办法看看编译器如何将我的代码降低为更简单的代码?例如,我想看看如何调用所有复制构造函数,如何解决重载函数调用,所有模板扩展和实例化完成等等.现在我正在学习C编译器如何通过实验解释我的代码但是,只要看到我的代码降低形式就好了,即使它非常难看.我正在寻找类似于g -E的东西,它显示了预处理器的结果,但是对于C来说.
编辑:我应该补充一点,我不是在寻找一个反汇编程序. C源代码和汇编代码之间存在巨大差距.在这个鸿沟内部是复杂的事情,比如模板元编程和对运算符方法的各种隐式调用(赋值!强制转换!构造函数!…)以及具有非常复杂的分辨率规则的重载函数等等.我正在寻找工具,以帮助我理解C编译器如何解释我的代码.现在,我唯一能做的就是尝试一些实验,然后逐步了解编译器正在做什么.我想看看有关正在发生的事情的更多细节.例如,在调试模板元编程问题时,这将有很大帮助. 解决方法
目前,我认为你最好的选择是Clang(你可以在
Try Out LLVM页面上尝试一些简单的代码).
使用Clang / LLVM编译C,C或Obj-C时,您可以要求编译器发出中间表示(LLVM IR),而不是完全采用汇编/二进制形式. LLVM IR是编译器内部使用的完整指定语言: > CLang将C代码降低到LLVM IR IR是机器特定代码之前的最后一步,因此您不必学习特定的汇编指令,而且您仍然可以非常低级地表示真正发生的事情. 您可以在优化之前和之后获得IR,后者更能代表实际代码,但远离您最初编写的内容. C程序示例: #include <stdio.h> #include <stdlib.h> static int factorial(int X) { if (X == 0) return 1; return X*factorial(X-1); } int main(int argc,char **argv) { printf("%dn",factorial(atoi(argv[1]))); } 相应的IR: ; ModuleID = '/tmp/webcompile/_10956_0.bc' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [4 x i8] c"%d A 0" define i32 @main(i32 %argc,i8** nocapture %argv) nounwind { ; <label>:0 %1 = getelementptr inbounds i8** %argv,i64 1 %2 = load i8** %1,align 8,!tbaa !0 %3 = tail call i64 @strtol(i8* nocapture %2,i8** null,i32 10) nounwind %4 = trunc i64 %3 to i32 %5 = icmp eq i32 %4,0 br i1 %5,label %factorial.exit,label %tailrecurse.i tailrecurse.i: ; preds = %tailrecurse.i,%0 %indvar.i = phi i32 [ %indvar.next.i,%tailrecurse.i ],[ 0,%0 ] %accumulator.tr1.i = phi i32 [ %6,[ 1,%0 ] %X.tr2.i = sub i32 %4,%indvar.i %6 = mul nsw i32 %X.tr2.i,%accumulator.tr1.i %indvar.next.i = add i32 %indvar.i,1 %exitcond = icmp eq i32 %indvar.next.i,%4 br i1 %exitcond,label %tailrecurse.i factorial.exit: ; preds = %tailrecurse.i,%0 %accumulator.tr.lcssa.i = phi i32 [ 1,%0 ],[ %6,%tailrecurse.i ] %7 = tail call i32 (i8*,...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str,i64 0,i64 0),i32 %accumulator.tr.lcssa.i) nounwind ret i32 0 } declare i32 @printf(i8* nocapture,...) nounwind declare i64 @strtol(i8*,i8** nocapture,i32) nounwind !0 = metadata !{metadata !"any pointer",metadata !1} !1 = metadata !{metadata !"omnipotent char",metadata !2} !2 = metadata !{metadata !"Simple C/C++ TBAA",null} 我个人发现它相对可读(一旦你超越了语言的原始发现,它试图保留变量名,有些,函数名仍然存在). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |