怎么看降低c

怎么看降低c,第1张

概述我正在努力提高对C实际工作原理的理解.有没有办法看看编译器如何将我的代码降低为更简单的代码?例如,我想看看如何调用所有复制构造函数,如何解决重载函数调用,所有模板扩展和实例化完成等等.现在我正在学习C编译器如何通过实验解释我的代码但是,只要看到我的代码降低形式就好了,即使它非常难看.我正在寻找类似于g -E的东西,它显示了预处理器的结果,但是对于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
> LLVM优化IR
> LLVM后端(例如x86)从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("%d\n",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"%dA"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.itailrecurse.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.ifactorial.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,...) nounwinddeclare 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}

我个人发现它相对可读(一旦你超越了语言的原始发现,它试图保留变量名,有些,函数名仍然存在).

总结

以上是内存溢出为你收集整理的怎么看降低c全部内容,希望文章能够帮你解决怎么看降低c所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1244367.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存