![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
编译器
文章平均质量分 64
我是标同学
我非常喜欢编程
展开
-
c语言编译器UCC学习旅程 总结与感悟
在2013年上本科时候,刚开始学c语言时,程序编译运行。就很神奇,编译过程中,编译器怎么就知道成千上万行代码中哪句代码有问题,能定位到某一行某一列,甚至还能提示你如何修改代码,这是如何做到的呢,也太奇妙了吧!!!尽管有这样的疑惑,但是当时的我实在太菜,也不是计算机专业,于是也没有深究。但是这个疑惑和好奇一直伴随着我。后面读了计算机研究生,决定解开这个迷惑,寒假期间,于是按照网上推荐,买了经典的编译原理龙书,虎书等等多本书,看了感觉还是很高深,于是去B站看了哈工大老师的编译原理视频,感觉自己好像懂了,但是原创 2022-05-12 13:14:49 · 1578 阅读 · 2 评论 -
UCC编译器学习笔记21
在汇编代码生成中,一个很重要的问题就是寄存器的分配。在计算机中,CPU 的速度比内存的速度快得多,编译器应尽量有效地利用寄存器资源,减少对内存的不必要访问,从而提高由编译器生成的汇编代码的运行速度。在中间代码生成阶段,UCC 编译器用临时变量 t 来存放形如“t: a+b;”的公共子表达式的值;到了汇编代码生成时,UCC 编译器会尽可能地把这些公共子表达式的值存放在寄存器,当需要再次重用时,就可以直接由相应的寄存器中得到。不过,CPU 中寄存器的资源是很有限的,在 32 位的 x86 芯片上,原创 2022-05-10 17:16:55 · 462 阅读 · 0 评论 -
x86汇编知识以及应用详解
基础知识:指令规则:movl $0 %eax,把常数0加载到eax寄存中。这里的后缀字母l表示long:4字节,此外还有w表示word:2字节(为了服从传统而已,其实现代意义的word就是4字节了),b表示byte:1字节。寄存器前面都得加个%,我猜这个是从编译器的指令模板来的,编译的指令模板就是movl %0 %1这样,其中%0表示占位符,也就是待替入的寄存器。x86的栈是高地址--->低地址增长的形式。x86寄存器名字不好记,没有arm的叫法容易区分(arm是R0-R15,多好听呀)。原创 2022-05-10 13:58:28 · 2761 阅读 · 0 评论 -
UCC编译器学习笔记20
UCC 编译器内部用英文单词 generate 来表示中间代码的生成,而用 emit 来表示汇编代码的生成,这里我们统一翻译为“生成”。第 30 至 34 行的代码用于保存寄存器的值,第 35 行用于在栈空间中预留内存空间,用来存放局部变量和临时变量,这部分工作被称为“Prologue 序言”,即在函数开始执行时要处理的工作。而图 6.1.1 第 53 至 57 行被称为“Epilogue 尾声”,用于恢复原先保存的寄存器值,第 58 行的汇编指令 ret 用于从栈中取出返回地址并返回。而函原创 2022-05-09 23:51:30 · 608 阅读 · 0 评论 -
UCC编译器学习笔记19
switch case语句和if else语句到底有什么区别:switch case语句要求case后必须是常量,因此要求更为严格,但是该语句的执行效率最高,可以认为在O(1)时间匹配到目标分支执行。这是为什么呢,看下面switch (a)case constant1: xx;case constant2: xx;case constant3: xx;。。。编译器把case语句后面的常量进行了表格化跳转,就是和地址直接绑定在了一块,这样可以直接跳转,如下:case 0:原创 2022-05-09 16:16:44 · 520 阅读 · 0 评论 -
UCC编译器学习笔记18
我们再分析条件表达式的翻译,以下给出了一段 C 程序及其对应的中间代码,我们生成临时一个临时变量 t0 用来存放 b+2 或 b+3 的值,然后再把 t0 赋值给变量 c。/************************************************************************Syntax conditional-expression: logical-OR-expression...原创 2022-05-09 09:00:57 · 341 阅读 · 0 评论 -
UCC编译器学习笔记17
UCC在处理数组和结构体成员的时候,都是直接转为偏移值了,偏移值是以字节为单位,例如:int (*ptr)[4] = &arr;(*ptr)[2] ---> ptr[0][8] -----> (ptr, 8)ptr 是指向 int[4]数组的指针, C 程序员通过(*ptr)[2]来访问数组元素时,UCC 编译器会在语义检查CheckUnaryExpression 时构造成一棵形如([] ([] ptr 0) 8)的语法树(8是以字节为单位的),在翻译这个语法树时,我们会计算原创 2022-05-07 21:21:59 · 917 阅读 · 0 评论 -
UCC编译器学习笔记16
方案2中,无论a为真还是假,都只需要跳转一次,但是方案1不是,因此UCC编译器选的是第二种中间代码生成方案。这个其实是个模板,就是待判断的表达式为真,则跳转到F2,否则顺序执行块会跳到Next2块。其实指令的执行,就分为两种,顺序执行,跳转执行(引起了控制流的改变)。顺序执行的最小单元,叫做块bblock。那么生成指令时候,无非就是执行指令(不需要产生有向边),或者跳转到块的指令(由于这个是一个块要到另一个块了,因此同时会产生一条有向边)...原创 2022-05-07 10:53:52 · 411 阅读 · 0 评论 -
UCC编译器学习笔记15
关于结构体中,位域成员的赋值原理:struct PTE{int offset : 12;int pgNo : 20;}struct PTE pte = {64,3};给pte赋值,其实就是 (3<<12) | 64原理:由于struct PTE占32位,3想赋值给第二个成员,而64想赋值给第一个成员,而64的高12位一定会为0的(这是程序员肯定会控制的)...原创 2022-05-05 12:48:14 · 509 阅读 · 0 评论 -
主流编译器比较
这里比较Clang和gcc:clang只需要完成词法和语法分析,代码优化和机器代码的生成工作由llvm完成。所以和全部由自己包下的gcc比起来,clang可以更专注地做好一件事。这种结构也使clang可以被单独拿出来用在其他的程序里。比如vim的clang_complete插件就是利用clang进行语法分析后给出精确的自动补全和语法错误提示的。而gcc就没法很方便地做到这一点。在实用性方面,除了有更快的编译速度更快和更友好的出错提示外,clang还内置有静态分析工具,可以对代码进行静态分析(原创 2022-05-05 12:19:32 · 559 阅读 · 0 评论 -
UCC编译器学习笔记14
语法分析,并没有构建出类型系统,只是构建出关系骨架语义分析,才赋予了每个标识符灵魂原创 2022-05-04 19:20:50 · 498 阅读 · 0 评论 -
UCC编译器学习笔记13
我们来思考个问题:int a;int a[3][4];假如有两个定义,现在我们要想描述出标识符a的类型信息,我们会怎么做呢,对于第一句代码:下面的Type类型中的categ置为一个数,即可表明它的类型了。 对于第二句代码:a不仅需要int信息,还有,它是指针信息,还有它是指向int * [3][4]的这些信息,这个仅仅Type类型中的成员是无法表述的了,因此需要最下面的typeDerivList类型,也就是复合类型,用来描述该标识符的更多信息。除了数组外,函数,指针,等也属于符合类型,有多原创 2022-05-04 09:42:25 · 1175 阅读 · 0 评论 -
UCC编译器学习笔记12
assert函数/***********************************************************assert(sym->kind == SK_TypedefName);(void)((e)||_assert(#e, __FILE__, __LINE__))(void)((sym->kind == SK_TypedefName)||_assert("sym->kind == SK_TypedefName", __FILE__,原创 2022-05-03 22:09:18 · 404 阅读 · 0 评论 -
UCC编译器学习笔记11
语义检查就是建立成最完善的类型系统,这些类型是我们能读懂的信息了。而被声明的标识符的类型信息正好是分布在 DeclarationSpecifiers 和 Declarator 中,通过调用第 29 或 46 行的 DeriveType函数,会把这两部分的类型信息组合到一起,构造完整的类型信息。例如,对于 int arr[4]来说,int 是其声明说明符,而 arr[4]是声明符,只有把 int 和[4]组合到一起,我们才能得到arr 的类型信息为 int [4]。...原创 2022-05-03 21:22:07 · 433 阅读 · 0 评论 -
UCC编译器学习笔记10
编译器如何实现遇到编译错误后,能继续往下编译,这样能在一次编译中尽可能找出所有错误,给报出来,这样程序员可以一次性修改这些错误了,如下:if(!IsIntegType(swtchStmt->expr->ty)){Error(&stmt->coord,"Theexpressioninaswitchstatementshallbeintegertype.");swtchStmt->expr-&...原创 2022-05-03 17:49:02 · 343 阅读 · 0 评论 -
UCC编译器学习笔记9
typedef struct type{TYPE_COMMON} *Type;中的structtype*bty;域,表示该类型的第二个属性,比如如果是指针变量,指针本身是int型,但是bty这个域就是指向的那个类型原创 2022-05-03 10:25:10 · 243 阅读 · 0 评论 -
UCC编译器学习笔记8
语法检测是根据文法进行检测的语义检查就是根据语义规则进行检查的(比如两个类型是否可以相互转换),这个语义规则文档,就是<http://flash-gordon.me.uk/ansi.c.txt>原创 2022-05-02 19:27:41 · 430 阅读 · 0 评论 -
UCC编译器学习笔记7
库函数 printf()的代码在我们编写上述 hello.c 时就已经存在,这意味着被调函数 printf其实并不知道我们在调用它时,到底传递了几个实参。对 printf 而言,它只是按照格式化字符串的说明,从栈中取出相应的参数,如下所示:// 实际上只有 10 这一个参数,但 printf 看到有两个%d,// 于是仍试图从栈中取两个参数,打印出形如 10,1074172310 的垃圾值printf(“%d, %d “,10);// 实际上有 10,20,30 这 3 个参数,但 printf原创 2022-05-01 20:21:51 · 784 阅读 · 0 评论 -
UCC编译器学习笔记6
文法构成,三大基本单元:声明 Declaration、语句 Statement 和表达式 Expression由于文法产生式中,其实是包含了一些不符合真正语法规则的形式(也就是真正正确的程序是文法定义的程序的子集),因此需要来一次语义检查。语义检查就是对上述的大三单元进行合法性检测的过程...原创 2022-04-30 23:58:30 · 371 阅读 · 0 评论 -
UCC编译器学习笔记5
* declarator: * pointer declarator * direct-declarator * * direct-declarator: * ID * ( declarator ) * direct-declarator [ [constant-expression] ] * direct-declarator ( parameter-type-list ) * direct-declarator ( [identifier-list] ) * ..原创 2022-04-30 23:06:51 · 350 阅读 · 0 评论 -
UCC编译器学习笔记4
我们需要对 ucl\decl.c 的其他代码进行分析,才能更好理解图 3.3.4 和图 3.3.7 的语法树是如何构造出来的。这里可能有个问题,程序的原作者在编程时,在其脑海中就已经有其要构造的语法树的整体轮廓;但是,程序的阅读者在缺乏文档的情况下,只有读完大部分代码,做过分析后才能重构出这棵语法树的概貌。另一个问题是,C 标准文法刻画的是 C 语言这样的无穷集合,不同的 C 程序对应不同的语法树,而在书中,我们只能选取一些如上所示的简单而又有一定代表性的代码来举例,在还没有介绍完 ucl\dec原创 2022-04-30 19:42:27 · 462 阅读 · 0 评论 -
UCC编译器学习笔记3
文法中最重要的部分:declaration (声明)原创 2022-04-29 19:12:38 · 1126 阅读 · 0 评论 -
UCC编译器学习笔记2
表达式构成一颗语法树(就是把程序中有用的信息组织串起来),例如 expression: a,b,c 其中expression的语法如下: 这个其实是一个左递归文法,其实表达的就是assignment-expression,assignment-expression,assignment-expression,...... 即多个assignment-expression 而我们在写程序解析的时候,就是递归调用自己,会形成上面的树形结构。文法的左递归和又递归会分别反应出该运算符(比如上面就是指逗号)的原创 2022-04-29 12:33:50 · 354 阅读 · 0 评论 -
UCC编译器学习笔记1
标准C语言,结构体中的成员是可以指定所占位数的,下面的ST类型表示struct st *typedef struct st{int a:8;int b:24;int c;}* ST原创 2022-04-28 16:17:28 · 1407 阅读 · 0 评论