GCC编译器后端移植技术

时间:2022-08-06 08:32:18

GCC编译器后端移植技术

摘要:从GCC编译器的体系结构出发,提出了GCC前后端分离的结构以适合移植到不同的硬件平台,分析了GCC后端移植的关键技术。重点阐述后端移植所必须的文件,并详细说明这些文件的作用,给出了RTL中间语言的语法结构以及典型指令的RTL指令模板结构。最后通过一个实例对移植到新硬件体系结构的GCC进行测试,结果表明针对特定的硬件体系结构,GCC后端移植技术是可行的,能够产生正确的汇编语言代码。

关键词:RTL中间语言; 指令模板; 机器描述MD; 后端移植

中图分类号:TN91934; TP314文献标识码:A文章编号:1004373X(2012)06003904

GCC compiler rearend porting technology

L Pengwei, YUAN Chengjun, HE Li

(Xi’an Microelectronics Technology Institute, Xi’an 710054, China)

Abstract: Proceeding from the GCC compiler system structure, the separation of GCC frontend and rearend structures is put forwards to suit the transplantation to different hardware platforms. The key technology of GCC rearend porting is analyzed. The details and functions of these documents needed by the rearend porting are presented. The intermediate language grammar structure of RTL and typical instruction template structure of RTL instructions are provided. Finally, an example of the GCC transplanted to a new hardware system structure were tested. The results show that GCC rearend porting to the specific hardware system structure is practicable, which can produce the correct assembly language code.

Keywords: RTL intermediate language; instruction template; MD; GCC rearend porting

收稿日期:201109130引言

近年来,嵌入式计算机系统被广泛应用于军事及空间领域的各种控制及智能系统中。在这些系统中,嵌入式计算机是系统的核心和智能部件。随着集成电路技术的发展,开始设计生产具有自主产权的专用芯片,并越来越多的将其应用于航空航天等相应嵌入式计算机系统中。同时嵌入式计算机应用的不断发展给计算机技术的各个方面提出了新的要求和挑战。嵌入式系统的开发特征对开发工具提出了特殊的要求。它对于代码大小,代码性能,以及可配置性的苛刻要求,使得在桌面以及服务器端开发中表现良好的编译系统往往不能胜任。这需要为其开发专用的高级语言编译器,但是开发一个完全自主化的编译器往往需要很长时间,并不是一个可取的方案,所以把目光转向可变目标编译器[1]。可变目标编译器能够针对不同的目标机器生成代码。编译器中与机器有关的部分被独立成模块,针对不同的目标机器,这些模块可以方便的进行替换。GCC就是是可变目标编译器,作为开源编译器,它源码丰富,文档详尽,是一个支持多种高级语言和多机器平台的系统,高度优化和可移植性能是该编译系统最为突出的2大特点。本文将详细介绍GCC移植相关的技术。

1GCC体系结构

GCC(GNU Complier Collection)是一个成功的支持多种高级语言和多种机器平台的系统。GCC体系结构(如图1所示)可以划分为2部分:与语言相关,目标机器无关的前端和与语言无关,目标机器相关的后端。

图1GCC体系结构它是一个典型的语法制导的优化编译器[23],前端通过词法分析,语法分析,语义分析,生成语法树,对语法树简单优化之后,将其转化为中间代码。后端接受前端产生的语法树,将其转换为中间语言的表现形式,在此基础上进行各种优化,然后根据目标机的机器描述生成汇编程序代码[4]。

GCC要实现支持多平台编译,必须解决3个根本问题:需要设计一种较好的中间语言,在适当的层次上,向上能支撑多种语言的映射,向下能够适合多平台转换并且适合于各种优化;需要设计一种对目标机恰当的机器描述;在机器描述与编译主体之间需要仔细的设计一种统一接口。将GCC移植到一个新的硬件系统时,上述3个问题的解决是致关重要的。由于GCC前端与语言相关[5],已经很成熟稳定,能够支持当今流行的大部分高级语言,如C/C++,Java,Fortran,Ada 等,所以不对前端做过多介绍,着重介绍后端技术。

2RTL中间语言

RTL(Register Transfer Language)[6]是一种以一种虚拟寄存器(Pseudo register)的方式来叙述计算机行为的语言。RTL有5种对象:表达式,整数,宽整数,字符串和向量。其中最重要的是表达式RTX(RTL Expression)。RTX类似于C的结构体,通常用指针来引用它,指针类型定义名为rtx。每个RTX都具有统一的内部数据结构与外部语法。本文只涉及RTX的外部语法,即RTX表达式的文本形式的语法,其一般形式为:(code: m opn1 opn2 ……),

code:RTX操作码。该操作码指明RTX表示的操作类型,如表示一条指令时进行某种说明。此外,code还确定RTX的操作数个数和这些操作数的种类。

m:机器模式。表示数据和运行结果的类型,它反映了数据类型与字长两部分信息。数据类型分为整型,浮点型和复型3种。机器字长则分为8位,16位,32位,64位等。这两部分信息组合所构成的机器方式反映了机器能表示的各种数据类型。

opn:操作数。各个RTX表达式的操作个数以及操作数的种类是各不相同的,这取决于RTX操作码。以下是一个实际的RTX表达式例子,

(insn 7 6 0 (set (mem:SI (plus:SI (reg:SI 54 virtualstackvars)

(const_int 12 [0xfffffff4])) [0 a+0 S4 A32])

(const_int 3 [0x3])) 1 (nil))

操作码“insn”指出这是一条表示指令的RTX,前3个操作数均为整常数,分别表示本条指令编号,前一条指令编号和后一条指令编号,构成前向链和后向链(如图2所示)。其对应的树结构(如图3所示)。

3GCC后端技术

GCC后端对于目标机器的支持全部体现在后端描述中,将GCC移植到一个新的硬件系统时,要对新系统的处理器架构要进行详细的描述,使GCC的后端支持新的处理器架构。本节重点介绍后端描述的结构以后端描述的自动处理。

图2insn对象的双向链表图3RTX表达式及其对应的树结构3.1GCC后端描述

GCC对于后端的描述主要有3个文件[7],一个是C语言宏文件,一个C源文件,一个用RTL表达式写成的机器描述文件MD。将GCC移植到一个新的硬件系统时,要对新系统的处理器架构要进行详细的描述,使GCC的后端支持新的处理器架构。具体的描述文件就是上述3个文件:C的宏文件,C文件和机器描述文件MD,分别为target.h,target.c和target.md,target是需要移植的目标机器的代号。下面分别介绍3种文件。

3.1.1C的宏文件

C的宏是用来描述机器和ABI的属性。一般分成以下几类:

(1)控制GCC驱动程序选项,目标机器的特定命令行选项。这些宏定义告诉编译驱动程序以何种形式的命令行参数运行诸如预处理,编译,汇编,连接等处理步骤,在运行这些处理步骤中可能需要的查询路径名以及是否需要运行某一些特殊的处理步骤等。

(2) 存储布局:要涉及基本的数据类型的大小,对齐约定;

(3) 应用二进制编程接口(ABI),如何调用函数;

(4) 目标机器的寄存器使用,包括类型,基本特征,寄存器分配的顺序,用于构造堆栈的寄存器指令等等;

(5) 寻址模式,描述目标机器不同的寻址模式;

(6) 汇编文件输出框架格式约定,指定汇编程序的初试数据段,正文段,一般数据段等等的格式要求,定义汇编输出函数的函数名;

(7) 调试信息输出约定,指定系统支持的调试文件格式。

这些参数,其中很多不是参数核集的元素,有缺省的处理方式,但要具体地描述一个特定平台,须对它们作正确而有效的定义。它们是绝大多数平台至少提供的内容,只能描述出平台最基本的功能。

3.1.2C源文件

target.h中定义的宏都是生成代码,这给调试增加了一定的难度和复杂度,所以在target.c文件中增加一个同名函数(但是为小写字母)。例如,在target.h文件中,定义了这样一个宏:

#define PREFERRED_RELOAD_CLASS(X,CLASS)preferred_reload_class (X, CLASS)

为了让其可用,并保证程序的可读性,引入了target_protos.h文件,在target_protos.h中,声明了同名函数:

extern enum reg_class preferred_reload_class(rtx, enum reg_class)

并且在target.c文件中具体定义了此函数。这是一个约定,在配置的时候,配置程序会做处理。由此,可以调试这个函数,而不必在众多的文件中增加宏定义。

3.1.3机器描述MD

机器描述MD中用RTL语言描述的指令模板是核心内容。MD文件是目标机指令集的一个形式化的说明文件,它针对GCC中的各种操作模式,描述了指定目标机支持的操作和实现情况,而并非目标指令集的简单汇集。编译系统根据由机器描述MD生成的数据结构和函数定义集合,进行中间代码的生成以及中间代码到汇编代码的映射。这些“标准指令”是从各种目标机的指令集中抽象出来的,但同时它又能表达GCC中的各种基本操作。,下面是指令模板的一般结构[8]:

(define_patterntype "(optional)patternname"

[RTLtempalte]

"optional paternalcondition"

"outputtemplate"

(optinally:[attributesetting])

)

简单介绍以下各个参数的含义:

(1)patterntype 有2种类型,insn是用于定义指令样板的RTX表达式中最核心的一种类型,既可作为生成模板,又可作为匹配模板;expand是模板的扩充定义,仅在操作与标准名称模板相关时使用。

(2) patternname 指令模板名,一个模板可以为GCC规定的标准指令名,或者开发者任意给定的名字,也可以空字符串,但是模板名必须惟一。

(3) RTLtempalte一个复杂操作的集合,为一不完全的RTX表达式或向量,称为RTL模板。它表示指令模板的RTL指令体,只规定了RTL指令体中的各种操作以及操作数的位置和操作数必须满足的条件和限制,并未指明具体的操作数。

(4) optional paternalcondition 为一字符串,称为条件。这个字符串或者为空,或者为一个C语言条件表达式。当非空时,它指出此模板有效的条件。

(5) outputtemplate 为一字符串,称为输出模板。输出模板用来确定与此模板相匹配的RTL指令的汇编输出形式。

(6) attributesetting 它为一任选的RTX向量,称为指令属性。当此操作数出现时,它给出与这一模板相匹配的指令属性。

下面是mips.md中的一条单浮点加法指令模板:

(define_insn "addsf3"

[(set(match_operand:SF 0 "register_operand" "=f")

(plus:SF(match_operand:SF 1 "register_operand"

"f") (match_operand:SF 2 "register_operand" "f")))]

"TARGET_HARD_FLOAT"

"add.s\t%0,%1,%2"

[(set_attr "type""fadd")

(set_attr "mode""SF")])

这是一条单浮点加法指令的指令模板[9],分别对应指令模板结构的各个参数的含义。从这个指令模板,可以看出这条指令的模板类型patterntype是insn;模板名patternnames是"addsf3",这是指令名,从指令名可以看出这是一条单浮点加法指令;这条指令有3个操作数,RTL模板规定了3个操作数的各种操作和位置以及必须满足的条件和限制条件,"set" ,"mem","plus"分别表示赋值,存储器引用和加法运算,它们的操作数均为rtx表达式;指令模板是否有效的条件是"TARGET_HARD_FLOAT";汇编输出模板是"add.s\t%0,%1,%2",输出的汇编代码形式就如输出模板所示;最后是指令属性,表明这是浮点加法指令,指令的模式为SF,是单浮点模式。

3.2GCC后端处理

机器描述文件MD建立抽象机标准指令、中间语言RTL、目标机汇编模板三者之间的联系,它是一个正文文件,如果编译过程中为构造或匹配RTL去搜寻这样一种文件,将会机器缓慢。为此GCC编译内部设计了专门的函数和数据结构作为编译主体与机器描述之间的接口,编译主体通过这些函数和数据结构获得MD的内容。在编译器的构造期间,利用GCC提供的一套独立的,专用的机器描述处理程序,将正文形式的MD转换成含有接口所需的数据结构与函数的C源程序。gen*正是完成这一工作的一套转换程序[10],对机器描述文件进行处理(如图4所示),生成一组C文件,或者头文件,生成的这些文件以及手工定义的target.c和target.h结合起来就是GCC的机器相关部分。

图4后端处理流程gen*是指一套11个C程序,它们针对不同的编译处理目的分析MD,生成相应一套接口程序包含11个C文件insn*.c,或者insn*.h。由gen*生成的这套接口程序分别作用于RTL的优化,机器相关的优化,汇编代码输出等过程。其中,insn*.h含有编译主体和insn*.c涉及到的宏名定义,数据类型定义以及外说明,它们作为头文件被包含于相关的源文件中。GCC通过使用生成的RTL代码片段对机器描述MD文件中的指令模板进行匹配。insnrecog.c中的函数recog()是依据MD中的指令样板生成的RTL指令匹配函数。给定一条RTL指令,该函数判断它是否与MD中的某条指令样板相匹配,若匹配则返回该样板的编号,否则返回1。对每一个RTL片段来说,都要从MD文件头开始扫描,逐个匹配直到找到一个insn定义的寄存器行为和RTL片段完全相同,输出相应的汇编代码。

4实例验证

将GCC移植到了自己开发的DSP芯片LSDSP上。首先要详细编写的目标机器后端描述文件[11] ,LSDSP.md,LSDSP.c和LSDSP.h,然后放在GCC源码包中相应的位置,通过配置源码中的configure脚本(具体参照GCC使用手册),经过编译后得到目标机编译环境。简单加法程序的测试结果(如图5所示)。

从测试结果可以看出,移植后的GCC可以支持新的硬件体系结构,能够产生符合标准的汇编代码。

5结语

GCC是支持多语言、多目标机编译系统中最有代表性的一个。虽然随着嵌入式应用的升温,优化的交叉编译系统正在得到越来越多的关注,但它还是一个比较新的课题,能参考的文献和技术资料非常有限,很多工作都是靠阅读大量的源代码完成的。现在对专用芯片移植编译器的技术已经有所了解,要想得到高效的优化的交叉编译环境,还有大量工作要做。

图5测试结果参考文献

[1]FRASER C W,HANSON D R.可变目标C编译器:设计与实现[M].王挺,黄春,译.北京:电子工业出版社,2005.

[2]MUCHNICK S S.高级编译器设计与实现[M].赵克佳,沈志宇,译.北京,机械工业出版社,2005.

[3]陈火旺,刘春林,赵克佳,等.程序设计语言编译原理[M].3版.北京:国防工业出版社,2009.

[4]刘坚.编译原理基础[M].西安:西安电子科技大学出版社,2002.

[5]金龙飞,刘磊.通用克扩展编译器前端生成器的设计与实现[J].吉林大学学报:理学版,2005(9):2527.

[6]杨川龙.基于GCC的嵌入式系统编译器的研究与开发[D].哈尔滨:哈尔滨工程大学,2006.

[7]PARTHEY Jan. Porting the GCCBackend to a VLIWarchitecture \[D\]. Chemnitz, Germany: Chemnitz University of Technology, 2004.

[8]汤睿.基于GCC的DSP芯片编译器的研究与开发[D].重庆:重庆邮电大学,2007.

[9]STALLMAN R M. MA 021111307 using the GNU compiler collection \[S\]. Boston, USA: GNU Press, 2004.

[10]冯刚.基于GCC的嵌入式系统编译器研究与开发[D].杭州:浙江大学,2004.

[11]刘飞,孙永节,孙海燕.基于C6x平台的GCC编译器移植[J].科技信息,2010(7):5960.

上一篇:基于VB程序数据库登录权限问题的研究 下一篇:基于FPGA的Kalman滤波器实现研究