一种代码编译方法、装置及电子设备与流程

文档序号:31084277发布日期:2022-08-09 22:48阅读:49来源:国知局
1.本发明涉及计算机
技术领域
:,特别是涉及一种代码编译方法、装置及电子设备。
背景技术
::2.在函数中往往声明了一个或多个局部变量,并且执行函数的过程中需要频繁使用这些局部变量,因此为提高函数的执行效率,相关技术中将局部变量存储于寄存器中。而寄存器在存储局部变量之前可能已经存储有其他数据,将局部变量存储于寄存器将导致其他数据被破坏,造成该其他数据所属的程序无法正常执行。因此,相关技术中在将局部变量存储于寄存器前,先将寄存器内已经存储的数据存储至栈中,该过程称为入栈。3.在局部变量较多的应用场景中,需要入栈的寄存器的数目也较多,将使用大量的栈空间,导致作为栈空间的高速内部内存不足,而使用低速的外部低速内存作为栈空间继续进行入栈,而将外部低速内存作为栈空间使用程序运行时会让数据入栈、出栈的效率降低,从而导致函数的执行效率降低。技术实现要素:4.本发明实施例的目的在于提供一种代码编译方法、装置及电子设备,以提高函数的执行效率。具体技术方案如下:5.本发明的第一方面,提供了一种代码编译方法,所述方法包括:6.获取以高级语言编写的、用于实现目标函数的高级语言代码;7.若所述目标函数的函数属性中包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第一汇编代码,其中,所述第一汇编代码中不包括控制目标寄存器进行入栈的代码,所述目标寄存器为所述第一汇编代码中约定用于存储所述目标函数中局部变量的寄存器。8.在一种可能的实施例中,所述方法还包括:9.获取初始掩码,所述初始掩码用于标识所述第一寄存器,其中,所述第一寄存器为所述目标寄存器中确定会入栈的寄存器;10.根据所述初始掩码,修改编译器的初始后端中对应于所述第一寄存器的代码,得到编译器的重编后端,所述重编后端编译得到的汇编代码中不包括控制对所述第一寄存器进行入栈的代码;11.所述将所述高级语言代码编译为用于实现所述目标函数的第一汇编代码,包括:12.用包含所述重编后端的编译器编译所述高级语言代码,得到第一汇编代码。13.在一种可能的实施例中,所述方法还包括:14.根据所述初始掩码确定所述目标寄存器中所述第一寄存器的数量,以使得所述编译器根据所述第一寄存器的数量调整栈空间的分配。15.在一种可能的实施例中,所述用包含所述重编后端的编译器编译所述高级语言代码,得到第一汇编代码,包括:16.将所述高级语言代码转换为以预设中间表示语言编写的中间表示代码;17.用所述重编后端编译所述中间表示代码,得到第一汇编代码。18.在一种可能的实施例中,所述方法还包括:19.若所述目标函数的函数属性中不包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第二汇编代码,其中,所述第二汇编代码中包括控制对目标寄存器进行入栈的代码。20.本发明的第二方面,提供了一种代码编译装置,所述装置包括:21.代码获取模块,用于获取以高级语言编写的、用于实现目标函数的高级语言代码;22.代码编译模块,用于若所述目标函数的函数属性中包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第一汇编代码,其中,所述第一汇编代码中不包括控制目标寄存器进行入栈的代码,所述目标寄存器为所述第一汇编代码中约定用于存储所述目标函数中局部变量的寄存器。23.在一种可能的实施例中,所述装置还包括:24.掩码获取模块,用于获取初始掩码,所述初始掩码用于标识所述第一寄存器,其中,所述第一寄存器为所述目标寄存器中确定会入栈的寄存器;25.重编后端模块,用于根据所述初始掩码,修改编译器的初始后端中对应于所述第一寄存器的代码,得到编译器的重编后端,所述重编后端编译得到的汇编代码中不包括控制对所述第一寄存器进行入栈的代码;26.所述代码编译模块具体用于,用包含所述重编后端的编译器编译所述高级语言代码,得到第一汇编代码。27.在一种可能的实施例中,所述装置还包括:28.空间确定模块,用于根据所述初始掩码确定所述目标寄存器中所述第一寄存器的数量,以使得所述编译器根据所述第一寄存器的数量调整栈空间的分配。29.在一种可能的实施例中,所述代码编译模块包括:30.中间表示获取子模块,用于将所述高级语言代码转换为以预设中间表示语言编写的中间表示代码;31.代码编译子模块,用于用所述重编后端编译所述中间表示代码,得到第一汇编代码。32.在一种可能的实施例中,所述装置还包括:33.第二代码编译模块,用于若所述目标函数的函数属性中不包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第二汇编代码,其中,所述第二汇编代码中包括控制对目标寄存器进行入栈的代码。34.本发明的第三方面,提供了一种电子设备,其特征在于,包括处理器、通信接口、存储器和通信总线,其中,处理器,通信接口,存储器通过通信总线完成相互间的通信;35.存储器,用于存放计算机程序;36.处理器,用于执行存储器上所存放的程序时,实现上述第一方面任一所述的方法步骤。37.本发明的第四方面,提供了一种计算机可读存储介质,其特征在于,所述计算机可读存储介质内存储有计算机程序,所述计算机程序被处理器执行时实现上述第一方面任一所述的方法步骤。38.本发明实施例有益效果:39.本发明实施例提供的代码编译方法、装置及电子设备,可以根据目标函数的函数属性确定目标函数是否需要复原寄存器内原先存储的数据这一特点,在目标函数的函数属性包含预设目标属性时,将高级语言代码编译为第一汇编代码,由于第一汇编代码中不包括控制对目标寄存器进行入栈的代码,且目标寄存器为第一汇编代码中约定用于存储目标函数中局部变量的寄存器,因此在通过执行第一汇编代码实现目标函数的过程中,将局部变量写入寄存器前并不会对寄存器进行入栈,有效降低了需要写入栈的数据的数量,降低了栈空间的使用,避免使用外部低速内存扩充栈空间,提高了程序运行过程中函数的执行效率。40.当然,实施本发明的任一产品或方法并不一定需要同时达到以上所述的所有优点。附图说明41.为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,还可以根据这些附图获得其他的实施例。42.图1为本发明实施例提供的代码编译方法的一种流程示意图;43.图2为本发明实施例提供的代码编译方法的另一种流程示意图;44.图3为本发明实施例提供的代码编译方法的另一种流程示意图;45.图4为本发明实施例提供的代码编译方法的另一种流程示意图;46.图5为本发明实施例提供的代码编译装置的一种结构示意图;47.图6为本发明实施例提供的电子设备的一种结构示意图。具体实施方式48.下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员基于本发明所获得的所有其他实施例,都属于本发明保护的范围。49.通常在网络数据包的处理过程中,为提高处理速度,np(networkprocessor,网络处理)芯片通常会使用几千个硬件线程来并行处理网络数据包。然而芯片的面积是有限的,在处理器数量增加的情况下,势必需要通过其他优化方案来兼顾性能和芯片面积。例如在内存上就会考虑缩小芯片内部的高速内存容量,扩大外部内存的容量来满足小的芯片面积和巨大的内存空间。在栈空间的安排上,优先使用芯片内部的高速内存,当内部的高速内存耗尽后,使用外部的低速内存来扩充栈空间。但是外部内存的访问速度要远低于内部内存,使用外部内存作为栈空间将会极大影响网络数据包的处理速度,因此,要提高数据处理效率,需要减少栈空间的使用,以避免因使用过多栈空间而耗尽内部的高速内存。而对寄存器进行入栈需要占用一定的栈空间,因此需要尽量减少寄存器的入栈。基于此,本发明提供了一种代码编译方法,如图1所述,方法包括:50.s101,获取以高级语言编写的、用于实现目标函数的高级语言代码。51.s102,若目标函数的函数属性中包括预设目标属性,将高级语言代码编译为用于实现目标函数的第一汇编代码。52.选用该实施例,可以根据目标函数的函数属性确定在目标函数的返回阶段是否需要复原寄存器内原先存储的数据这一特点,在目标函数的函数属性包含预设目标属性时认为目标函数在返回阶段不需要复原目标寄存器内原先存储的数据,因此在执行目标函数的过程中在将局部变量写入寄存器的存储的数据被覆盖前对该寄存器入栈,因此可以将高级语言代码编译为第一汇编代码,由于第一汇编代码中不包括控制对目标寄存器进行入栈的代码,且目标寄存器为第一汇编代码中约定用于存储目标函数中局部变量的寄存器,因此在通过执行第一汇编代码实现目标函数的过程中,将局部变量写入寄存器前并不会对寄存器进行入栈,有效降低了需要写入栈的数据的数量,降低了栈空间的使用,避免使用外部低速内存扩充栈空间,提高了程序运行过程中函数的执行效率。53.另一方面,本实施例中第一汇编代码是由高级语言代码编译得到的,即本实施例能够基于目标函数的函数属性,自动地通过汇编代码合理安排目标函数对栈空间的使用,使得开发人员无需掌握汇编语言,只需为基于高级语言开发的程序中各函数合理设置函数属性,即可合理安排程序对栈空间的使用。有效降低了开发难度。54.其中,在s101中,高级语言是一种独立于机器,面向过程或对象的语言,即高级语言不能够被机器直接识别,对于高级语言编写的代码需要经过编译器编译后才能够被机器执行。高级语言是较接近自然语言和数学公式的语言,用人们更易理解的方式编写的语言,例如java(一种计算机编程语言)语言,c语言,c++语言等都为高级语言。通常将使用高级语言编写的程序称为源代码,即本发明中用于实现目标函数的高级语言代码,根据使用的高级语言的不同,用于实现同一目标函数的高级语言代码也会不同。55.其中,在s102中,第一汇编代码中不包括控制目标寄存器进行入栈的代码,目标寄存器为第一汇编代码中约定用于存储目标函数中局部变量的寄存器。56.对应于高级语言代码,汇编代码为使用汇编语言编写的代码,汇编语言是任何一种能够被电子计算机、微处理器、微控制器或其他可编程器件直接识别的低级语言。通过汇编语言提供的指令,在汇编代码中可以自由安排寄存器和栈空间的使用,而高级语言中缺乏用于安排寄存器和栈空间的使用的指令。因此,将获取的高级语言代码编译为用于实现相同目标函数的第一汇编代码,能够在第一汇编代码中安排栈空间和寄存器的使用。57.寄存器是cpu(centralprocessingunit,中央处理器)内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和/或运算结果。局部变量是指在一个函数内部或复合语句内部的变量,其作用域是定义该变量的函数或定义该变量的复合语句。局部变量的生存期是从函数被调用的时刻算起到函数的返回阶段结束。由于寄存器的访问速度远高于内存的访问速度,因此局部变量会优先被存储在寄存器中,本文中将用于存储目标函数中的局部变量的寄存器称为目标寄存器。58.每个函数都具有其对应的属性,例如javascript(一种计算机编程语言)开发的程序中函数具有length(长度)属性和name(名字)属性等,本发明实施例中的预设目标属性用于标识函数在返回阶段不需要复原寄存器内原先存储的数据,即在将该函数的局部变量存储至寄存器前不需要对寄存器入栈,该预设目标属性预先在目标函数对应的体系结构中进行了属性定义,例如arm(advancedriscmachines,进阶精简指令集机器)体系结构的函数的属性定义在gcc/config/arm目录下,而arc体系结构的函数的属性定义在gcc/config/arc目录下。作为一种示例,arc体系结构的函数的属性定义在arc.c文件的arc_attribute_table数组中,该数组已经定义了若干个特定于arc(一种处理器)体系结构的函数的属性,要增加一个预设目标属性仅需在该数组中添加一行即可。示例代码如下:[0059][0060]其中,“{"no_call_saved",……}”为在数组中添加的一行代码,该示例中预设目标属性的名字为no_call_saved。可以理解的是,上述代码只是作为一种示例,其中预设目标属性的名字可以自行定义,并不限定于“no_call_saved”,只要该预设目标属性的名字不与预先已经定义的属性的名字相同即可。基于此,对于在返回阶段不需要复原寄存器内原先存储的数据的函数,可以用预设目标属性进行标识,使得后续在编译的过程中通过该预设目标属性确定是否对该目标函数进行栈空间和寄存器的优化处理,即确定是否将目标函数编译为第一汇编代码。[0061]具体的,确定目标函数的函数属性是否包括预设目标属性,可以通过本发明实施例提供的代码编译方法的执行主体(如计算机、手机等电子设备)在执行过程中判断,若包括,则通过执行主体将高级语言代码编译为用于实现目标函数的第一汇编代码。在一种可能的实施例中,还可以是若通过编译器检测到目标函数的函数属性中包括预设目标属性,将高级语言代码通过编译器编译为用于实现目标函数的第一汇编代码。[0062]编译器若检测到目标函数的函数属性中包括预设目标属性,如以前述目标属性为“no_call_saved”为例,则若编译器检测到“no_call_saved”这个函数属性,则将实现该目标函数的高级语言代码编译为第一汇编代码,其中,得到的第一汇编代码中不包括控制目标寄存器进行入栈的代码,以使得该高级语言代码被执行的过程中目标寄存器都不进行入栈。[0063]还是以预设目标属性的名称为“no_call_saved”为例,在检测目标函数的函数属性是否包括预设目标属性时,可以在编译器中增加一个判断目标函数是否具有预设目标属性的函数,如前所述,以预设目标属性的名称为“no_call_saved”为例,在编译器可以增加相应的函数“arc_no_call_save_p”,来检测目标函数的函数属性中是否有“no_call_saved”属性,代码示例如下:[0064][0065]arc_no_call_save_p函数的参数fun是目标函数,fun可以是以高级语言代码的形式表示的,也可以是以中间表示显示的,中间表示为高级语言代码在经过编译器的前端和中间优化处理后得到的一种用于表示目标函数的表示形式,treeattr=type_attributes(tree_type(decl))这行代码在被执行时用于从这个中间表示中提取出目标函数的函数属性定义部分的内容。可以理解的是,一个被编译的目标函数可以同时有多个函数属性,lookup_attribute("no_call_saved",attr)则专用于搜索被编译的目标函数是否有"no_call_saved"属性。如果没有,编译器的该函数返回null_tree,arc_no_call_save_p返回假,编译器后续不对目标函数进行的寄存器的入栈数量优化处理,即不将目标函数对应的高级语言代码编译为第一汇编代码。如果有"no_call_saved"属性,返回真,编译器需要进一步对目标函数进行优化处理,即将目标函数对应的高级语言代码编译为第一汇编代码。[0066]选用该实施例,可以通过编译器实现对目标函数的预设目标属性高效检测和编译,提高了代码编译方法的编译效率。[0067]在网络数据包处理的应用场景中,网络数据包处理函数通常是一个无限循环,并行运行在几千个硬件线程上的函数,该函数通常不会返回,形式如下:[0068][0069]而如前所述,将目标寄存器入栈的目的是为了在函数返回时使用之前入栈的值来恢复目标寄存器,从而保证函数返回后程序也能正常运行。由于网络数据包处理函数不需要返回,也就不需要将目标寄存器入栈。因此选用上述实施例,可以给网络数据包处理函数添加一个预设目标属性,让编译器识别该预设目标属性,并在进行栈空间分配时,不需要将该网络数据包处理函数用来存放局部变量的目标寄存器入栈,进而减少栈空间的使用。例如若有13个目标寄存器不用入栈,每个目标寄存器32位宽,有4096个硬件线程,那么每个硬件线程可以节约32/8×13=52字节的栈空间,每个硬件线程的内部内存栈空间一般比较小,通常是256字节,这样就能节约20%的内部内存栈空间。[0070]因此,选用本发明实施例,可以根据需求和本领域技术人员的经验为不需要返回的函数(如网络数据包处理函数)直接设置预设目标属性来减少其栈空间的使用,进而提高数据处理效率,提高了代码编译的灵活性和适用性。[0071]并且,使用汇编代码可以自由安排寄存器和栈空间,因此,相关技术在面对目标函数需要优化寄存器和栈空间的需求时,通常都要求目标函数是使用汇编语言编写和维护的,再对该目标函数使用相应的编译器来编译,例如使用汇编语言撰写目标函数时通过gcc(gnucompilercollection,gnu编译器套件,gun为一种操作系统)的naked扩展属性来标记目标函数,后续编译的时候不会自动生成寄存器入栈的相关代码。然而相对于网络数据包处理函数这样的复杂函数,若直接使用汇编语言进行函数编写和维护会非常困难。因此,相关技术中的方案无法适用于复杂函数。[0072]而选用本发明的上述实施例,复杂函数可以直接以高级语言进行编写,本发明通过在复杂函数的函数属性中添加预设目标属性来识别该目标函数是否需要优化寄存器入栈,并在编译过程中对其优化,避免了将复杂函数也通过汇编语言进行编写而造成的编写和维护的困难,提高了代码编译的适用性。[0073]在一种可能的实施例中,若目标函数的函数属性中不包括预设目标属性,将高级语言代码编译为用于实现目标函数的第二汇编代码,其中,第二汇编代码中包括控制对目标寄存器进行入栈的代码。[0074]可以理解,若目标函数的函数属性不包括预设目标属性,则说明目标函数在返回阶段需要复原目标寄存器内原先存储的数据,因此,在编译该目标函数对应的高级语言代码时就不需要将原本会入栈的部分目标寄存器调整为不入栈,即,并不对目标函数的目标寄存器的入栈情况进行调整,因此,编译得到的第二汇编代码中会包括控制对目标寄存器进行入栈的代码。[0075]选用该实施例,根据目标函数的函数属性确定目标函数是否需要优化目标寄存器的入栈数量,在目标函数的函数属性不包括预设目标属性时,编译高级语言代码的过程中并不对目标函数的目标寄存器的入栈情况进行调整,可以根据需求和实际情况对目标函数使用不同的编译方式,提高了代码编译方法的灵活性。[0076]具体的,对高级语言代码进行编译可以使用编译器进行编译,而相关技术中并不存在在编译过程中优化高级语言代码对应的目标函数的寄存器的入栈数量的方案,基于此,本公开还提供了一种代码编译方法,如图2所示,方法包括:[0077]s201,获取初始掩码。[0078]s202,根据初始掩码,修改编译器的初始后端中对应于第一寄存器的代码,得到编译器的重编后端。[0079]s203,获取以高级语言编写的、用于实现目标函数的高级语言代码。[0080]其中,在s203与前述s101相同,具体请参见s101中的相关描述,此处不再赘述。[0081]s204,若目标函数的函数属性中包括预设目标属性,用包含重编后端的编译器编译高级语言代码,得到第一汇编代码。[0082]其中,在s201中,初始掩码用于标识目标寄存器中的第一寄存器,其中,第一寄存器为目标寄存器中确定会入栈的寄存器。具体的,由于不同体系结构对栈空间使用的计算集中固定在不同的函数中,因此,初始掩码对应于不同体系结构的函数和编译器,其所在位置也不同。作为一种示例,arc体系结构对栈空间使用的计算集中在arc_compute_frame_size函数中,该函数会根据正常流程进行计算,将会入栈的第一寄存器标记在gmask变量中,gmask变量为32位,每个位代表一个寄存器,如果gmask变量的某个比特位置1,则表示该比特位对应的寄存器需要入栈。因此,针对于arc体系结构下的目标函数,初始掩码表示的第一寄存器即为gmask变量中的比特位为1的寄存器。可以理解的是,初始掩码会根据体系结构的不同而不同,上述只是以arc体系结构作为一种示例,本发明并不限定初始掩码只能为arc体系中gmask变量中各位的值。[0083]其中,在s202中,重编后端编译得到的汇编代码中不包括控制对第一寄存器进行入栈的代码。[0084]该编译器可以是gcc编译器,也可以是除gun编译工具链之外的其他编译工具,本发明对此并不限定。[0085]编译器经过多年的发展,形成了三段式编译过程,分别是前端、优化和后端。前端用于将不同的高级语言代码转换为编译器内部统一的中间表示,每一种高级语言都有一个对应的前端。优化阶段对中间表示进行优化,后端用于将优化后的中间表示翻译为特定于体系结构的汇编代码,也可以针对特定的体系结构进行特殊的优化。每个体系结构都有一个对应的后端,编译器的后端可以生成多种体系结构的汇编代码。由于汇编代码可以用于自由调整栈空间和寄存器,并且编译器的后端是用于翻译得到汇编代码的,因此,若需要通过汇编语言优化目标函数的第一寄存器的入栈情况,则需要相应的调整编译器的初始后端,使编译器在编译高级语言代码的过程中使用调整后的重编后端来优化目标函数的寄存器的入栈情况。[0086]具体的,初始掩码标识了目标函数中将要入栈的第一寄存器,因此,在修改编译器的初始后端时,可以将对应于第一寄存器的代码相应修改,使得后续编译后得到的第一汇编代码中第一寄存器不再入栈。还是以上述arc体系结构的目标函数为例,如前所述,若gmask变量中的某个比特位为1,则说明该比特位对应的寄存器为第一寄存器,将要入栈,可以理解的是,编译器的初始后端在编译目标函数对应的高级语言代码时并不会对gmask的比特位为1的值进行修改,因此后续编译得到的汇编代码会使第一寄存器入栈。而若要让这些第一寄存器不入栈,则需要修改初始后端的代码,使得得到的重编后端在编译目标函数对应的高级语言代码时将第一寄存器对应在gmask中的比特位清0。示例代码如下:[0087][0088][0089]其中,if(arc_no_call_save_p(cfun))如前所述,是用于判断被编译的函数是否具有no_call_saved属性的,如果有该预设目标属性,则在for(regno=13;regno《=25;regno++)循环中从bit13开始到bit25结束逐位判断gmask的位的值,而arc体系结构规定r13-r25寄存器在被调函数中要使用则必须先入栈,函数返回时出栈恢复,因此,在判断arc体系结构的目标函数中的第一寄存器时,只要在r13-r25寄存器中判断即可。[0090]在if(gmask&(1《《regno))中,1《《regno表示将1左移regno个位数,&为位与符号,gmask&(1《《regno)表示将gmask与位移后的1《《regno进行位与操作,确定结果是否为1,可以理解的是,在位与运算中,当两个数值对应的位都为1,其结果才为1,示例性的,若gmask的值为00111100000000000000,regno的值为15,则1《《regno的值为00000100000000000000,将gmask与1《《regno位与之后得到的结果为00000100000000000000,说明gmask的比特位的第15位值为1,其对应的寄存器为第一寄存器。可见,如此通过将1在第13位到第25位之间进行位移,使其循环与gmask的第13位到第25位的比特值进行位与,根据得到的位与结果是否包含1来确定出gmask中第13到25位是否有为1的值,若为1则说明gmask该比特位对应的寄存器为第一寄存器将会入栈,以此根据初始掩码确定出第一寄存器。[0091]gmask&=~(1《《regno)用于在确定出gmask中具体哪些比特位为1后,将这些比特位置0,~表示按位取反,将gmask中确定出比特位的值为1对应的位清0,使得该比特位对应的第一寄存器后续不会入栈。基于上述代码,修改编译器的初始后端,得到编译器的重编后端,使得编译得到的汇编代码不包括控制第一寄存器入栈的代码。[0092]可以理解的是,上述示例只是以arc体系结构中根据初始掩码修改编译器的初始后端来得到重编后端的步骤作为一种示例,实际上,不同的体系结构的编译器中都有一个对应的初始后端,因此,在不同体系中根据初始掩码修改初始后端后也会得到不同的重编后端,这样使得编译器可以根据不同的体系结构生成不同体系结构对应的汇编代码。因此,本发明的方案和思路也可以应用在其他体系结构中(如arm),本发明对具体根据初始掩码,修改编译器的初始后端中对应于第一寄存器的代码,得到编译器的重编后端的方法并不限定,[0093]其中,在s204中,由于编译器已经进行修改,重编后端能够将目标函数中本身将要入栈的第一寄存器对应的高级语言代码,编译为第一寄存器不入栈的第一汇编代码,优化了目标函数中的第一寄存器的入栈数量,节省了栈空间,进而提高了函数的数据处理效率。[0094]选用该实施例,可以提供一种编译高级语言代码的编译器,通过该编译器编译用高级语言代码实现的目标函数的同时,能够优化目标函数的寄存器的入栈数量,节省栈空间,在提高了函数的数据处理效率的同时,提高了代码编译效率。[0095]在一种可能的实施例中,后端不是直接将高级语言代码转换为汇编代码,而是将高级语言代码对应的中间表示转换为汇编代码。基于此,本发明还提供了一种代码编译方法,如图3所示,方法包括:[0096]s301,获取初始掩码。[0097]此步骤与s201相同,具体请参见s201中的相关描述,此处不再赘述。[0098]s302,根据初始掩码,修改编译器的初始后端中对应于第一寄存器的代码,得到编译器的重编后端。[0099]此步骤与s202相同,具体请参见s202中的相关描述,此处不再赘述。[0100]s303,获取以高级语言编写的、用于实现目标函数的高级语言代码。[0101]此步骤与s101相同,具体请参见s101中的相关描述,此处不再赘述。[0102]s304,将高级语言代码转换为以预设中间表示语言编写的中间表示代码。[0103]s305,用重编后端编译中间表示代码,得到第一汇编代码。[0104]其中,在s304中,如前所述,编译器包括前端、优化和后端三个部分,而前端用于将不同的高级语言代码使用预设中间表示语言转换为编译器内部统一的中间表示代码,优化阶段在对中间表示代码进行优化。可以理解的是,高级语言代码有很多不同种类,而通过编译器的前端和优化阶段可以将高级语言代码转换为统一的中间表示代码,方便后续的重编后端对中间表示代码进行统一的高效处理,使得重编后端并不需要对不同的语言的高级语言代码进行针对性的特殊编译。[0105]其中,在s305中,重编后端对其可以理解的统一的中间表示代码进行编译,得到第一汇编代码。[0106]选用该实施例,将不同的高级语言代码转换为统一的中间表示代码,使得重编后端可以对统一的中间表示代码进行编译得到汇编代码,并不需要针对不同语言的高级语言代码分别生成重编后端,提高了代码编译的适用性。[0107]在减少了需要入栈的寄存器后,后续入栈的数据在栈空间中的存储位置也将相应发生改变,因此用于标识这些后续入栈的数据再栈空间中的存储位置的栈指针需要对应改变,因此,如果仅仅在目标函数中减少了需要入栈的寄存器而不改变栈指针,可能导致后续其他数据的入栈数据错误,基于此,本发明还提供了一种代码编译方法,如图4所示,方法包括:[0108]s401,获取初始掩码。[0109]此步骤与s201相同,具体请参见s201中的相关描述,此处不再赘述。[0110]s402,根据初始掩码,修改编译器的初始后端中对应于第一寄存器的代码,得到编译器的重编后端。[0111]此步骤与s202相同,具体请参见s202中的相关描述,此处不再赘述。[0112]s403,获取以高级语言编写的、用于实现目标函数的高级语言代码。[0113]此步骤与s101相同,具体请参见s101中的相关描述,此处不再赘述。[0114]s404,若目标函数的函数属性中包括预设目标属性,用包含重编后端的编译器编译高级语言代码,得到第一汇编代码。[0115]此步骤与s204相同,具体请参见s204中的相关描述,此处不再赘述。[0116]s405,根据初始掩码确定目标寄存器中所述第一寄存器的数量,以使得编译器根据第一寄存器的数量调整为栈空间的分配。[0117]其中,在s405中,如前所述,初始掩码用于表示目标寄存器中的第一寄存器,即将要入栈的寄存器,因此,可以根据初始掩码确定出原本要入栈的第一寄存器的数量,从而使得编译器在编译的过程中确定出原本要入栈的寄存器入栈后占用的栈空间大小,以便编译器根据原本占用的栈空间的大小,确定出后续需要入栈的数据的栈指针。作为一种示例,还是以前述arc体系结构为例,可以在编译器中增加一行代码“reg_size-=units_per_word”使得在编译过程中每次对gmask中比特位的值为1的位清零之后计算一次未入栈的第一寄存器在栈空间中占用的空间大小,其中,reg_size是计算的将要入栈的第一寄存器入栈后占用栈空间的大小,而由于编译得到的第一代码中不包括对第一寄存器进行入栈的代码,所以通过reg_size-=units_per_word来将reg_size的值减少一个第一寄存器占用的栈空间大小,units_per_word是一个表示一个寄存器占用栈空间大小的宏。后续编译器即可根据reg_size确定出需要入栈的数据的栈指针。具体完整代码示例如下:[0118][0119]可以理解的是,上述代码只是以arc体系结构作为示例得到的,本发明的上述方案并不限定值用于arc体系结构中,对于其他体系结构,其也可以根据其体系结构中的初始掩码确定出第一寄存器的数量,并应用其体系结构中对应的函数代码计算出其对应的栈空间,进而为后续的数据分配正确的栈指针。[0120]选用该实施例,在优化了目标函数的第一寄存器的入栈数量后,可以使得后续的代码不受影响而继续入栈或出栈,合理分配了栈空间,避免了数据存储错误,进而提高了代码编译的准确性。[0121]为了更好的说明上述代码编译方法的具体实施过程,下面将结合具体的应用场景进行说明:[0122]在arc体系结构下,gcc编译器的初始后端代码集中在gcc/config/arc目录下,对于arc体系结构的编译器的初始后端,函数属性的识别及处理,函数栈空间的使用安排都在gcc源码树的gcc/config/arc/arc.c文件中实现,因此,在给编译器添加用于检测目标函数的预设目标属性的检测函数时,需要在arc.c文件中的arc_attribute_table数组中处理添加。[0123]针对于目标函数的预设函数属性可以为前述的“no_call_saved”,相应在,在编译器中添加的用于检测“no_call_saved”的检测函数的可以为前述的“arc_no_call_save_p”。在编译器的编译过程中,首先会通过前端将目标函数对应的高级语言代码转换为中间表示代码,优化阶段再对中间表示代码进行优化,后端用于将优化后的中间表示代码编译为汇编代码。若目标函数的函数属性中包含“no_call_saved”,则编译器的后端在编译该目标函数对应的中间表示代码的过程中可以通过“arc_no_call_save_p”检测出来,并确定出该目标函数需要进行寄存器的入栈优化。[0124]而若要在编译器的后端编译中间表示代码时对寄存器的入栈数量进行优化,使得得到的第一汇编代码控制第一寄存器不入栈,则需要相应的继续修改原编译器的初始后端代码。arc体系结构对栈空间使用的计算集中在arc_compute_frame_size函数中,该函数会将要入栈的寄存器标记在gmask变量中。如前述内容,gmask的比特位的值可以作为初始掩码标识该比特位对应的寄存器是否为第一寄存器,因此,编译器可以根据gmask确定出第一寄存器,进而将编译器初始后端在编译中间表示代码时控制第一寄存器入栈的代码修改为控制第一寄存器不入栈的代码,并且,由于后续还有其他需要入栈的数据继续入栈,而原本入栈的第一寄存器若不入栈,则需要确定出其在栈空间所占空间,从而为后续需要入栈的数据确定出正确的入栈地址,因此,在重编后端中还可以增加reg_size-=units_per_word代码,来在编译中间表示时计算出第一寄存器所占的空间。具体代码示例如下:[0125][0126][0127]上述代码已经在前述s405中进行过解释,此处不再赘述。可以理解的是,若编译器在编译高级语言代码的过程中检测到其对应的目标函数中包含预设目标属性,则会通过重编后端根据初始掩码编译该目标函数对应的中间表示,得到控制第一寄存器不入栈的第一汇编代码。相应的,若编译器没有检测到目标函数中包含预设目标属性,则在后续重编后端在编译目标函数对应的中间表示时就不会获取初始掩码,也不会对其原本需要入栈的第一寄存器对应的汇编代码进行相应的修改,而是生成第二汇编代码,使得该代码控制目标寄存器中的第一寄存器进行入栈。[0128]选用该实施例,通过修改gcc编译器的代码使得使用高级语言代码实现的arc体系的目标函数在编译的过程中能够对寄存器的入栈数量进行优化,节省了栈空间,使得高速内存足够作为栈空间进行使用,减少了使用低速内存作为栈空间从而导致的函数数据处理效率低的问题。[0129]对应于本发明实施例提供的代码编译方法,本发明实施例还提供了一种代码编译装置,如图5所示,包括:[0130]代码获取模块501,用于获取以高级语言编写的、用于实现目标函数的高级语言代码;[0131]代码编译模块502,用于若所述目标函数的函数属性中包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第一汇编代码,其中,所述第一汇编代码中不包括控制目标寄存器进行入栈的代码,所述目标寄存器为所述第一汇编代码中约定用于存储所述目标函数中局部变量的寄存器。[0132]在一种可能的实施例中,所述装置还包括:[0133]掩码获取模块,用于获取初始掩码,所述初始掩码用于标识所述第一寄存器,其中,所述第一寄存器为所述目标寄存器中确定会入栈的寄存器;[0134]重编后端模块,用于根据所述初始掩码,修改编译器的初始后端中对应于所述第一寄存器的代码,得到编译器的重编后端,所述重编后端编译得到的汇编代码中不包括控制对所述第一寄存器进行入栈的代码;[0135]所述代码编译模块502具体用于,用包含所述重编后端的编译器编译所述高级语言代码,得到第一汇编代码。[0136]在一种可能的实施例中,所述装置还包括:[0137]空间确定模块,用于根据所述初始掩码确定所述目标寄存器中所述第一寄存器的数量,以使得所述编译器根据所述第一寄存器的数量调整栈空间的分配。[0138]在一种可能的实施例中,代码编译模块502包括:[0139]中间表示获取子模块,用于将所述高级语言代码转换为以预设中间表示语言编写的中间表示代码;[0140]代码编译子模块,用于用所述重编后端编译所述中间表示代码,得到第一汇编代码。[0141]在一种可能的实施例中,所述装置还包括:[0142]第二代码编译模块,用于若所述目标函数的函数属性中不包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第二汇编代码,其中,所述第二汇编代码中包括控制对目标寄存器进行入栈的代码。[0143]本发明实施例还提供了一种电子设备,如图6所示,包括处理器601、通信接口602、存储器603和通信总线604,其中,处理器601,通信接口602,存储器603通过通信总线604完成相互间的通信,[0144]存储器603,用于存放计算机程序;[0145]处理器601,用于执行存储器603上所存放的程序时,实现如下步骤:[0146]获取以高级语言编写的、用于实现目标函数的高级语言代码;[0147]若所述目标函数的函数属性中包括预设目标属性,将所述高级语言代码编译为用于实现所述目标函数的第一汇编代码,其中,所述第一汇编代码中不包括控制目标寄存器进行入栈的代码,所述目标寄存器为所述第一汇编代码中约定用于存储所述目标函数中局部变量的寄存器。[0148]上述电子设备提到的通信总线可以是外设部件互连标准(peripheralcomponentinterconnect,pci)总线或扩展工业标准结构(extendedindustrystandardarchitecture,eisa)总线等。该通信总线可以分为地址总线、数据总线、控制总线等。为便于表示,图中仅用一条粗线表示,但并不表示仅有一根总线或一种类型的总线。[0149]通信接口用于上述电子设备与其他设备之间的通信。[0150]存储器可以包括随机存取存储器(randomaccessmemory,ram),也可以包括非易失性存储器(non-volatilememory,nvm),例如至少一个磁盘存储器。可选的,存储器还可以是至少一个位于远离前述处理器的存储装置。[0151]上述的处理器可以是通用处理器,包括中央处理器(centralprocessingunit,cpu)、网络处理器(networkprocessor,np)等;还可以是数字信号处理器(digitalsignalprocessor,dsp)、专用集成电路(applicationspecificintegratedcircuit,asic)、现场可编程门阵列(field-programmablegatearray,fpga)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件。[0152]在本发明提供的又一实施例中,还提供了一种计算机可读存储介质,该计算机可读存储介质内存储有计算机程序,所述计算机程序被处理器执行时实现上述任一代码编译方法的步骤。[0153]在本发明提供的又一实施例中,还提供了一种包含指令的计算机程序产品,当其在计算机上运行时,使得计算机执行上述实施例中任一代码编译方法。[0154]在上述实施例中,可以全部或部分地通过软件、硬件、固件或者其任意组合来实现。当使用软件实现时,可以全部或部分地以计算机程序产品的形式实现。所述计算机程序产品包括一个或多个计算机指令。在计算机上加载和执行所述计算机程序指令时,全部或部分地产生按照本发明实施例所述的流程或功能。所述计算机可以是通用计算机、专用计算机、计算机网络、或者其他可编程装置。所述计算机指令可以存储在计算机可读存储介质中,或者从一个计算机可读存储介质向另一个计算机可读存储介质传输,例如,所述计算机指令可以从一个网站站点、计算机、服务器或数据中心通过有线(例如同轴电缆、光纤、数字用户线(dsl))或无线(例如红外、无线、微波等)方式向另一个网站站点、计算机、服务器或数据中心进行传输。所述计算机可读存储介质可以是计算机能够存取的任何可用介质或者是包含一个或多个可用介质集成的服务器、数据中心等数据存储设备。所述可用介质可以是磁性介质,(例如,软盘、硬盘、磁带)、光介质(例如,dvd)、或者半导体介质(例如固态硬盘solidstatedisk(ssd))等。[0155]需要说明的是,在本文中,诸如第一和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、物品或者设备中还存在另外的相同要素。[0156]本说明书中的各个实施例均采用相关的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于装置、电子设备和计算机可读存储介质实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。[0157]以上所述仅为本发明的较佳实施例,并非用于限定本发明的保护范围。凡在本发明的精神和原则之内所作的任何修改、等同替换、改进等,均包含在本发明的保护范围内。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1