C编译器剖析_5.2.1 中间代码生成及优化_布尔表达式的翻译

C编译器剖析_5.3.1 中间代码生成及优化_If语句和复合语句的翻译 5.3.1   If语句和复合语句的翻译     我们先简单回顾一下对布尔表达式的翻译,我们通过调用TranslateBranch函数来产生跳转指令,从而实现布尔表达式的语义。在使用函数TranslateBranch(expr, bt, bn)时,有这么两个约定:     (1) 当expr为真时,跳往bt基本块;     (2) 紧随“函数TranslateBranch所生成的跳转指令”之 阅读详情

5.2.1  中间代码生成与优化_布尔表达式的翻译

    我们仍然按照语法分析和语义检查时的思路,先讨论表达式的翻译,再处理语句。表达式从概念上来说,可分为算术表达式和布尔表达式,在一些编程语言(例如Java)中对这两者是有严格区分的,算术表达式的结果是整数或浮点数,而布尔表达式的结果是逻辑上的真或假。布尔是英国数学家,由于布尔较早进行了关于“与或非”逻辑运算的研究,为了纪念这位先驱,在Java中引入了关键字boolean,而在C++中引入了bool关键字来表达逻辑上的真或假。C语言中并没有专门的布尔类型,而是把非0的值当作真,把0当作假。

int a, b;

if(a+b){// Java中非法,a+b为算术值,非布尔值;C中合法

}

if(a == b){//a == b为布尔值,在C或Java中都合法

}

    为了讨论的方便,我们不妨把C语言看成是存在布尔表达式,例如a&&b,a||b或者a>b等,也存在算术表达式,例如a+b或者a&b,但是不存在C程序员可见的布尔类型关键字bool或者boolean。对于算术表达式而言,C编译器需要对整个表达式进行求值,例如,我们要计算出“a和b相加的值”,或者“a和b按位与的值”,并把运算结果保存到一个临时变量中,这个临时变量的值就代表了整个表达式的值。而对于布尔表达式来说,我们并不会对整个表达式进行求值,而是生成相应的跳转指令,对于a&&b而言,当a为假时,不论b为何值,a&&b的值都为假,所以此时我们并不需要对b进行求值。若把“a&&b”换成“f()&&g()”,则当f()的返回值为假时,我们不需要对函数g()进行求值,此时g()函数根本就没有被调用,这就是C语言中的短路运算。

     我们先举个简单的例子来说明这些概念,如图5.2.1所示,第1至21行给出了一个简单的C程序,第22至60行是与之对应的中间代码。对于第4至8行的C代码来说,与其对应的中间代码在第24至31行,我们需要先对第4行的算术表达式a+b进行求值,第25行的中间代码“t0:a+b”表示把“a+b”求值后的结果存于临时变量t0中,对表达式进行求值的工作由ucl\tranexpr.c中的TranslateExpression()函数来完成。但对于第9行的布尔表达式a&&b来说,我们只是生成第33行和第35行的条件跳转指令,并没有对整个布尔表达式a&&b进行求值,但a为假时,控制流直接由第33行转移到基本块BB6处,即不再需要判断b的值。产生这些跳转指令的工作由ucl\tranexpr.c中的TranslateBranch()函数来实现。在X86汇编中,跳转指令对应的助记符为Jump,缩写为J;但在Arm汇编中,跳转指令对应的是Branch,缩写为B,单词Branch是分支的意思(也有些人写为分枝,哪个是错别字,whoknows!),这意味着如果是“有条件跳转”的话,控制流就会“开叉”,相当于一根树枝分成若干个细枝了,例如图5.2.1第35行的有条件跳转,控制流可能流向第37行,也可能流向第40行。


图5.2.1 布尔表达式和算术表达式

    对于图5.2.1第14行的算术表达式a&b来说,我们需要先对整个表达式a&b进行求值,再根据其结果进行跳转,如图第42和43行所示。比较特殊的是第19行的布尔表达式a||b,按我们之前的介绍,翻译布尔表达式时,我们只是产生一些跳转指令来改变控制流,如第50行和第52行所示。但按照第19行赋值语句的语义,我们需要在a||b为真时,给变量c赋值1;在a||b为假时,给变量赋值0。因此,C编译器需要产生第54至57行的代码。这些工作由ucl\tranexpr.c中的函数TranslateBranchExpression来完成。

    简而言之,如果我们需要显式地求出表达式的值,就调用函数TranslateExpression();如果只是需要生成一些跳转指令来改变当前的控制流,则使用TranslateBranch()。如果我们在调用TranslateExpression()来对表达式求值时,遇到的表达式是形如图5.2.1第19行的赋值语句中的布尔表达式a||b,此时我们就再调用TranslateBranchExpression()函数来处理,进而产生如图5.2.1第50至57行的代码。

    趁热打铁,我们现在就来看一下函数TranslateBranchExpression的代码,如图5.2.2第1至18行所示。第4行通过调用CreateTemp函数创建了一个临时变量,不妨设这个临时变量为t。我们需要根据布尔表达式的控制流来执行t=0或者t=1的代码,第11行调用GenerateMove函数产生t = 0的代码,第15行则用于产生t = 1。当表达式expr为假时,我们在执行完t=0后,还要通过第12行的GenerateJump函数,产生一条无条件跳转指令,跳过t=1这个指令。中间代码t=0是基本块falseBB的第一条指令,而t=1为基本块trueBB的第一条指令。在调用第8行的TranslateBranch函数来产生跳转指令时,我们需要把trueBB和falseBB作为跳转目标传递给TranslateBranch函数,这样我们才能生成形如如图5.2.1第50至52行的跳转指令。


图5.2.2 TranslateBranchExpression()

    当我们遇到形如“c = expression;”的语句时,由上下文可知,我们需要先对赋值号右侧的表达式进行求值,之后再结果赋给左侧的c。对右侧表达式进行求值的运算,由图5.2.2第45行的TranslateExpression

编译原理实战:从声明到控制流,中间代码生成全解析 本文深入解析编译原理中的中间代码生成过程,从声明语句到控制流翻译,详细介绍了三地址码的生成与应用。通过实际案例展示如何将高级语言转换为平台无关的中间表示,帮助开发者理解编译器内部工作原理,优化代码生成与调试效率。 阅读详情

相关推荐

编译原理实战:从SDT到三地址码的中间代码生成

本文深入探讨了编译原理中从语法制导翻译到三地址码生成的实战过程。详细解析了如何利用SDT为变量声明、赋值表达式及控制流语句生成中间代码,并重点介绍了高效处理控制流跳转的回填技术,为编译器后端优化与目标代码生成奠定坚实基础。

weixin_29215815的博客 100

GCC扩展与编译器优化实战:从分支预测到中间表示

编译器优化是提升程序性能的核心技术,其原理在于将高级语言代码高效转换为底层机器指令。通过分析程序的中间表示(IR),编译器应用多种算法进行优化,如死代码消除和公共子表达式消除,从而减少冗余计算、改善指令流水线效率。这项技术的价值在于,它能在不改变源代码逻辑的前提下,显著提升程序的执行速度和资源利用率,尤其适用于嵌入式系统、游戏引擎和高性能计算等对性能有极致要求的领域。在实际应用中,开发者可以借助编译器的扩展功能,例如GCC的`__builtin_expect`来引导分支预测,或通过预编译头文件加速大型项目的

405

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器04 LLVM编译器02

B-WUCL(用户权重均匀对比损失)和D-WUCL(物品权重均匀对比损失)中,动态调整参数λ_new(新用户补偿因子)和α(长尾补偿强度)是优化推荐系统适应数据分布变化的核心。

weixin_49199313的博客 1242

SLR(1)语法分析器原理与语法制导翻译实战

SLR(1)是一种经典的自底向上语法分析方法,其核心在于利用FOLLOW集解决LR(0)的移进-归约冲突,实现对上下文无关文法的高效识别。它通过项目集规范族构建分析表,在保证分析能力的同时控制计算复杂度,是理解编译器前端设计的关键技术路径。语法制导翻译则将语义动作嵌入语法规则,借助属性在分析栈中传递,驱动中间代码(如三地址码)的生成,形成从源码到可执行表示的结构化映射。该技术广泛应用于教学编译器、DSL解析器及静态分析工具开发。本文以可运行的SLR(1)实现为载体,深入剖析文法拓广、FOLLOW集计算、分析

weixin_34074740的博客 451

编译原理实战:从词法分析到中间代码生成的完整Java实现

编译原理是计算机科学的核心基础,它研究如何将高级编程语言转换为计算机可执行的机器代码。其核心流程包括词法分析、语法分析、语义分析和中间代码生成等阶段。词法分析器通过有限自动机将源代码字符流转换为有意义的单词序列;语法分析器则运用LL(1)、递归下降或SLR(1)等算法,依据文法规则验证并构建语法树,这是理解语言结构的关键。掌握这些原理对于构建解释器、代码分析工具乃至新型编程语言都至关重要。本文聚焦于**Java实现**的编译原理实验项目,通过剖析**北交大**的完整源码集合,详细展示了如何将抽象的First

weixin_29232121的博客 310

《编译原理课程设计》-布尔表达式的语法分析及语义分析程序设计

《编译原理课程设计》-布尔表达式的语法分析及语义分析程序设计

编译原理-简单编译器课程设计(C语言源代码)(附实验报告)

完成一个相对完整的编译器,该编译完成对变量类型(整数/浮点数)定义、赋值、四则运算、逻辑运算、跳转与循环控制功能。其输入是源程序(参见“一个四则运算源程序示例”),输出是所有变量的最终值。

a small c compiler DOS下小的C编译器

可运行在16位dos下的小的经裁剪的经典C编译器。 不含结构,联合,浮点计算,枚举等特性。 适合于编译器研究人员使用。包含源代码及可执行程序。

携程登录风控逆向踩坑实录:从滑块到点选验证码,我是如何一步步拿到phantom-token的

本文详细解析了携程登录风控系统的逆向过程,从滑块验证码到点选验证码的破解,再到设备指纹生成和加密协议逆向,最终成功获取phantom-token。文章提供了关键代码示例和实战技巧,帮助开发者理解并绕过复杂的风控机制。

weixin_28049429的博客 970

android 运动目标检测_MindSpore应用案例:AI对篮球运动员目标的检测

MindSpore作为一个端边云协同的开源的全场景AI框架,今年3月份开源以来,受到了业界的广泛关注和应用,欢迎大家参与开源贡献、模型众智合作、行业创新与应用、学术合作等,贡献您在云侧、端侧 (HiMindSpore 应用程序)、边侧以及安全领域的应用案例。MindSpore与您在AI领域共同成长,让AI使能千行百业,释放出强大的生产力。本文讲述的是MindSpore对篮球运动员目标的检测应用,通...

weixin_33603813的博客 834

Python 实现生命游戏及进化模拟完整指南

生命模拟是进化计算的一个特定子集,模拟了自然界中所观察到的自然过程,例如粒子或鸟群的聚集方式。生命模拟只是用来探索和优化问题的模拟形式之一,还有很多其他形式的模拟,可以更好地建模各种过程,但它们都源于康威生命游戏 (Conway’s Game of Life)。在本节中,我们将介绍生命模拟的基本概念,并使用 Python 实现康威生命游戏。

盼小辉丶的博客 7万+

材料仿真软件:Materials Studio_(14).电学性质计算

设置计算参数,包括 k 点网格、交换相关泛函等。

kkchenjj的博客 1863

`tokenizer.decode` 出现乱码或异常输出,怎么处理

摘要: 在使用Hugging Face Transformers库时,tokenizer.decode出现乱码或异常输出的解决方案包括:1)确保模型与分词器严格匹配,加载时使用trust_remote_code=True;2)谨慎处理特殊token,先保留所有token再针对性清理;3)校验模型输出token的维度和数值是否合法;4)通过convert_tokens_to_string替代解码;5)检查生成配置如max_new_tokens等参数。核心思路是确保模型与分词器逻辑对齐、输出token合法,必要

ZhangJiqun&191cm&85kg 584

10种电阻综合对比——《器件手册--电阻》

可变电阻在电子设备中也有很多用途,如在收音机的音量调节电路中,通过旋转可变电阻的旋钮来改变电路中的电阻值,从而改变通过扬声器的电流,实现音量的调节。根据电阻定律,电阻R = ρ(L/S),其中ρ是导体材料的电阻率,L是导体的长度,S是导体的横截面积。比如,同样材料制成的两根电线,粗的电线电阻比细的电线电阻小,长的电线电阻比短的电线电阻大。电流采样电阻的工作原理基于欧姆定律,即电阻两端的电压与通过电阻的电流成正比,公式为 I = V/R,其中 I是电流,V是电阻两端的电压,R 是电阻值。

XU157303764的博客 3138

Python 爬虫实战:赛事分析平台构建与比赛数据抓取

在体育赛事日益丰富的今天,对比赛数据的收集与分析对于运动员、教练团队以及体育爱好者都具有重要意义。通过构建一个赛事分析平台,我们可以系统地抓取、整理和展示各类比赛数据,为用户提供全面的赛事洞察。本文将深入讲解如何利用 Python 爬虫技术实现这一平台的构建,涵盖从目标网站分析到数据可视化展示的全过程。

u014481728的博客 3179

医学图像处理实战:利用OpenSlide解析病理SVS切片的完整解决方案

本文介绍了使用openslide处理病理SVS切片的完整流程,从基础安装到科研应用。主要内容包括:1)SVS切片特点及openslide工具简介;2)环境配置与软件安装;3)基础操作:读取切片、查看信息、可视化不同层级图像;4)进阶操作:坐标裁剪与批量处理;5)科研方向拓展:结合AI模型进行病理分割分类、量化分析及可视化报告。教程提供了完整的代码示例,帮助毕业设计学生快速掌握病理图像分析的核心技能。

m0_71589036的博客 309

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: C编译器剖析_5.1 中间代码生成及优化_简介
下一篇: C编译器剖析_5.2.2 中间代码生成及优化_再论符号symbol与公共子表达式
SheIsC
博客等级 码龄12年 224粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值