用于执行本机绑定的方法和装置的制作方法

文档序号:6489453阅读:213来源:国知局
专利名称:用于执行本机绑定的方法和装置的制作方法
技术领域
本发明总体上涉及计算机和计算机软件领域,并更特别地涉及用于例如翻译包含函数调用的程序代码的译码器、仿真器和加速器的程序代码转换方法和装置。
背景技术
在嵌入式和非嵌入式的CPU中,可发现这样的占优势的指令集体系结构(ISA),对于该体系结构存在大量软件,该体系结构出于性能考虑应被“加速”,或者“转换”成如果可透明地访问相关软件则可呈现更好的成本/性能好处的成千上万的有能力的处理器。还可发现被及时锁定在它们的ISA内且不会涉及到性能或市场范围的占优势的CPU体系结构。这种体系结构受益于“合成CPU”共同体系结构。
程序代码转换方法和装置有助于这种加速、翻译和共同体系结构能力,并且例如在2003年4月22日提交的共同未决的英国专利申请号03090560中提出,该申请标题为Block Translation Optimizationsfor Program Code Conversion,该专利申请的公开引入本文作为参考。
将被翻译的源(subject)程序通常包括多个源代码单元,其包括可执行的源自身以及多个源库,其中一些库可以是专用的,而一些库可被设置成该源OS的一部分(“系统库”)。当源程序运行时,由于对外部库进行函数调用,所以控制流在源代码的不同单元之间传递。在一些情况下,特定源库的本机(即目标体系结构)版本在目标体系结构上可用。
根据本发明,提供了一种在所附权利要求中说明的装置和方法。从从属权利要求以及下面的说明书中可清楚地看到本发明的优选特征。
下文概述了根据本发明的多个实施例可实现的多个方面和优点。其作为介绍以帮助本领域内的技术人员更快地理解详细的设计讨论,该讨论在下文给出生并且不会也不打算在任何意义上限制所附权利要求的范围。

发明内容
具体地,发明人开发了一种旨在加速程序代码转换的优化技术,该技术尤其可与采用源程序代码向目标代码的翻译的运行时翻译程序结合使用。提供一种本机绑定技术,该技术用于将在源代码向目标代码的翻译期间插入对本机函数的调用,从而源程序中的对源代码函数的函数调用在目标代码中被对相同函数的本机等效物的调用代替。将本机函数调用的参数从目标代码表示翻译成与本机代码表示、本机代码调用规约以及本机函数原型一致。
本机绑定是本发明的使翻译的源代码可直接执行代码单元的本机(即目标体系结构)版本而不是翻译和执行等效的源代码例如库的本机版本的机制。这避免了翻译这些库的源版本的开销。另外,本机版本可以是相同功能的有效得多的实现,因为本机版本可利用源版本不知道的目标体系结构的体系结构特征。


并入说明书且构成说明书的一部分的附图示出目前优选的实现,对该附图的说明如下图1是其中应用本发明的实施例的装置的框图;图2是示出根据本发明的一说明性实施例的本机绑定过程的示意图;图3是示出根据本发明的一说明性实施例的本机绑定过程的示意图;图4是示出根据本发明的一说明性实施例的本机绑定过程的示意图;
图5是示出根据本发明的一说明性实施例的本机绑定过程的示意图;以及图6是示出根据本发明的一说明性实施例的本机函数调用的流程图。
具体实施例方式
图1中示出用于实现下文讨论的多个新特征的说明性装置。图1示出目标处理器13,该处理器包括目标寄存器15,和存储多个软件构件17、19、20、21、22和28的存储器18。该软件构件包括将被翻译的源代码17、操作系统20、翻译程序代码19、翻译代码21、全局寄存器存储器27、本机绑定机制22和本机(native)代码28。翻译代码21还被称为目标代码21。全局寄存器存储器27还被称为源寄存器存储体27。翻译程序代码19例如可用作将一ISA的源代码翻译成另一ISA的翻译代码的仿真器,或用于将源代码翻译成相同ISA的翻译代码的加速器。本机代码28是针对目标处理器13直接编译的代码。
翻译程序19即实现翻译程序的源代码的编译版本,以及翻译代码21即翻译程序19产生的源代码17的翻译,与在目标处理器13上运行的操作系统20一起运行,该目标处理器通常为微处理器或其它合适的计算机。应理解,图1中所示的结构仅是示例性的,例如根据本发明的软件、方法和进程可以位于操作系统内或在操作系统之下的代码实现。源代码17、翻译程序代码19、操作系统20以及存储机制可以是本技术领域内的技术人员已知的各种类型的任意一种。
如文中使用的,“目标代码”21和“本机代码”28之间存在差别,该“目标代码”是由源代码17片段的运行时翻译产生的,该“本机代码”是为目标体系结构直接编译的。目标操作系统提供的系统目标库是本机代码28的一个示例。系统目标库的翻译是目标代码21的一个示例。本机代码28是在翻译程序19的外部生成的,这意味着翻译程序19不生成本机代码28,翻译程序19也没机会优化本机代码28。
在根据图1的装置中,程序代码转换优选地在运行时动态执行,同时目标代码21运行。翻译程序19按翻译程序21的顺序运行。上述翻译程序19通常用作为目标体系结构编译的应用程序。源程序17在运行时被翻译程序19翻译以在目标体系结构上直接执行。翻译程序19还变换源程序17进行的源操作系统(OS)调用,以便该调用在传递给目标OS 20时可正确地工作。
在生成目标代码21的进程中,根据源指令序列生成中间表示(“IR”)树。IR树是由源程序计算的表达式和执行的操作的抽象表示。随后,根据该IR树生成目标代码21。
文中所述的IR代码的集合被通俗地称为“树”。应指出,在形式上,这种结构实际上是有向非循环图(“DAG”)而不是树。树的形式定义要求每个节点最多有一个父节点。由于所述的实施例在IR生成期间使用公共子表达式删除,所以节点通常具有多个父节点。例如,标记影响指令结果的IR可被两个抽象寄存器参考,这两个寄存器对应于目的地源寄存器和标记结果参数。
例如,源指令“add %r1,%r2,%r3”执行将源寄存器%r2和%r3的内容相加,并将结果存储在源寄存器%r1内。因此,此指令对应于抽象表达式“%r1=%r2+%r3”。此示例包含具有包含两个代表指令操作数%r2和%r3的子表达式的加法表达式的对抽象寄存器%r1的定义。在源程序17的情形中,这些子表达式对应于其它、优先的源指令,或者它们可表示当前指令的细节例如立即常量。
当分析“加法”指令时,生成一个对应于用于加法的抽象数学运算符的新的“+”IR节点。该“+”IR节点存储对代表操作数的其它IR节点(在IR中表示为子表达式树,经常保持在源寄存器中)的参考。该“+”节点本身被源寄存器(用于%r1的抽象寄存器,指令的目的地寄存器)参考,该节点定义了该寄存器的值。例如,图20的中部偏右的部分示出对应于X86指令“add %ecx,%edx”的IR树。
本技术领域内技术人员应理解,在一个实施例内,翻译程序19使用面向对象的程序设计语言例如C++实现。例如,IR节点被实现为C++对象,并且对其它节点的参考被实现为对对应于那些其它节点的C++对象的C++参考。因此,IR树被实现为IR节点对象的集合,其包含彼此之间的多个参考。
此外,在讨论的实施例中,IR生成使用一组抽象寄存器。这些抽象寄存器对应于源体系结构的特定特征。例如,对于源体系结构上的每个物理寄存器存在唯一的抽象寄存器(“源寄存器”)。类似地,对于源体系结构上存在的每个条件码标记存在唯一的抽象寄存器。抽象寄存器在IR生成期间用作IR树的占位符。例如,位于源指令序列中的给定位置处的源寄存器%r2的值由特定的IR表达式树表示,该树与用于源寄存器%r2的抽象寄存器相关联。在一个实施例内,抽象寄存器实现为C++对象,其经由对特定IR树的根节点对象的C++参考与该树相关联。
抽象寄存器的实现在翻译程序代码19和目标代码21中的构件之间分配。在翻译程序19中,“抽象寄存器”是在IR生成期间使用的占位符,从而抽象寄存器与计算该抽象寄存器的值的IR树相关联,该特定抽象寄存器与该IR树相应。同样,翻译程序中的抽象寄存器可实现为C++对象,其包含对IR节点对象(即IR树)的参考。抽象寄存器组参考的所有IR树的集合体被称为工作IR森林(forest)(“森林”,这是因为其包含多个抽象寄存器根,每个该抽象寄存器根指代一个IR树)。该工作IR森林代表在源代码中的特定位置处的源程序的抽象操作的快照。
在基本块模式下,使用所有翻译代码序列可访问的存储区域即全局寄存器存储器27将状态从一个基本块传递到下一个基本块。该全局寄存器存储器27是抽象寄存器的储存库,每个该抽象寄存器对应于并仿真特定源寄存器的值或其它源体系结构特征。在执行目标代码21期间,抽象寄存器被保持在目标寄存器内以便它们可分享指令。在执行翻译程序代码21期间,抽象寄存器的值存储在全局寄存器存储器27或目标寄存器15内。
在目标代码21内,“抽象寄存器”是全局寄存器存储器内的特定位置,到和来自该位置的源寄存器的值与实际目标寄存器同步。可选择地,如果从全局寄存器存储器加载值,则目标代码21中的抽象寄存器应被理解为是目标寄存器15,该目标寄存器在目标代码21执行期间的对象寄存器的值被保存回该寄存器存储器内之前,临时保持该对象寄存器的值。
因此,在翻译程序19下运行的源程序具有以交织方式执行的两种不同类型的代码翻译程序代码19和目标代码21。翻译程序代码19是在运行时之前由编译程序根据翻译程序19的高层源代码实现的。目标代码21是在运行时期间由翻译程序代码19根据被翻译的程序的源代码17生成的。
该源处理器状态的表示同样在翻译程序19和目标代码21构件之间分配。翻译程序19将源处理器状态存储在多个显式编程语言器件例如变量和/或对象内;用于编译该翻译程序的编译器确定状态和操作如何以目标代码实现。相比而言,目标代码21将源处理器状态隐式地存储在目标寄存器和存储器位置,其被目标代码21的目标指令直接处理。
例如,全局寄存器存储器27的低层表示仅是分配的存储器的区域。这就是目标代码21如何通过在限定的存储区域和各个目标寄存器之间进行保存和恢复看到抽象寄存器并与抽象寄存器交互的。但是,在翻译程序19的源代码内,全局寄存器存储器27是可在更高层被访问和处理的数据阵列或对象。对于目标代码21,不存在高层的表示。
图2-5示出图1的翻译程序19的不同的说明性实施例。图2示出将被翻译程序105翻译的源代码17形式的源程序106的不同编译单元的说明性实施例。翻译程序105作为为本机体系结构(或者被称为目标体系结构)编译的可执行程序运行,其中该本机体系结构包括本机OS 103和本机处理器101(其等效于图1的目标OS 20和目标处理器13)。此示例内的源程序106包括源可执行程序107和多个源库,多个源库包括源专用库109和源系统库111。当不采用本机绑定时,源程序106的编译单元被翻译成目标代码21,并在翻译程序105内被执行。
图3示出其中在翻译的程序的代码的单元上利用本机绑定的说明性实施例的工作流程的框图。
源程序106包括源可执行程序107和多个源库,多个源库包括源专用库109和源系统库111。翻译程序105使用本机绑定以用对本机系统库117内的函数的调用来代替对源系统库函数111的源程序106调用。
例如,对于MIPS-x86翻译,x86系统目标库“libc”可定义一个高级的memcpy()(存储器复制)例程,该例程利用SSE2向量运算来执行非常快的字节复制。使用此申请内说明的本机绑定机制22,所有对MIPS源代码内的memcpy的调用都绑定到本机的memcpy()。这样消除了翻译memcpy()函数的源(MIPS)版本的成本。另外,memcpy()函数的本机(x86)版本可更好地认识到本机硬件的错综复杂,从而可得知最有效的实现该函数的预期效果的方式。
当检测到源程序的控制流进入源代码17例如源库的一部分——对于该部分存在源代码的本机版本——时,本机绑定由翻译程序19实现。翻译程序19执行等效的本机代码28而不是翻译源代码17。
除了目标系统库调用之外,本机绑定可用于更任意的代码替换,例如替换非库函数的本机编译的版本。此外,通过用替换本机函数代替对源系统函数的所有调用,可使用本机绑定在本机体系结构上实现源系统调用,该替换本机函数可实现与对源系统函数的调用相同的功能或用作围绕目标系统调用的调用分支(stub)。还可在除函数调用位置之外的任意源代码位置处应用本机绑定,以允许在源程序中的任何定义好的位置处插入或替换(目标代码或本机代码形式的)任意代码序列和/或函数调用。
绑定位置描述本机绑定机制22要求翻译程序19使特定的源代码17函数与它们的本机代码28的对应物相关联,从而翻译程序19知道将绑定哪些源函数以及哪些本机函数将与该源函数绑定。翻译程序19可根据本机绑定机制22的实现,以不同的方式获得此函数映射信息。
在一个实施例内,使用专用的“绑定位置”描述语言识别将被绑定的源函数。绑定位置描述包括(a)将被绑定的源函数和(b)将被绑定的对应的本机函数。翻译程序19在开始执行时读取绑定位置描述以识别绑定位置(将调用本机函数的位置)。在对源程序进行译码期间,当翻译程序19遇到这些绑定位置时,翻译程序19在目标代码21内插入对合适的本机函数的调用分支。在一个实施例内,具体的绑定位置描述嵌入在翻译程序19内。在另一实施例内,绑定位置描述存储在不同的文件内,翻译程序19在运行时读取该文件,从而允许终端用户通过添加特定的源到本机的函数映射来控制本机绑定结制22。
在另一实施例内,本机绑定绑定位置描述语言允许指定任意的绑定位置,从而除源函数调用之外,还可在源代码内的其它位置处插入本机函数调用。在此实施例内,绑定位置描述包括(a)源代码内定义的位置(即不只是函数调用位置)和(b)将绑定的对应的本机函数。例如,可将任意的绑定位置识别为(1)函数的起点;(2)源模块的初始化代码的起点;(3)偏离特定符号的固定偏移量(如偏离函数的起点的固定偏移量);(4)偏离模块中的第一正文段的固定偏移量;或(5)任何对特定源函数(在特定模块内,或在除该一个特定模块之外的所有模块内)的调用。绑定位置类型(1)和(5)之间的区别在于(1)绑定源函数的入口点而(5)绑定函数的调用位置。
在一些实施例内,本机绑定绑定位置描述语言允许终端用户指定相对的绑定位置,可在绑定位置(例如系统源函数调用)之前、之后或代替该位置,在该相对的绑定位置处插入本机函数调用。例如,本机绑定绑定位置描述可指定在所有对源函数“bar()”的调用之后马上调用本机函数“foo()”。
绑定位置描述语言还可用于在连接位置插入除本机函数调用之外的代码。在此实施例内,绑定位置描述包括(a)源程序内限定的位置和(b)对目标代码块或将被调用的本机代码程序的参考。如果插入的代码是目标代码21,则然后翻译程序19不需要在该绑定位置执行许多与参数变换和本机调用规约(下文将说明)相关联的工作,在该位置遵守翻译程序专用的目标代码调用规约就足够了。任意的目标和本机代码插入允许翻译程序19在翻译的程序上执行其它任务例如调试或性能模拟(profile)。
在可选择实施例内,在被称为运行时符号修补的过程中,在运行时之前在源程序的符号表中对将源到本机功能映射进行编码。运行时符号修补用特定的本机绑定标记符代替源程序的符号表中的条目。这需要在源程序在被编译(编译时间)之后但在被翻译(运行时)之前,处理该源程序。当翻译程序19在运行时遇到符号表标记符时,翻译程序19将符号表标记符解释成绑定位置描述,并解释它们以识别将调用哪个本机函数。在此实施例内,对将被绑定的源函数的识别在该符号表内的符号表标记符的位置是隐式的,这是因为该符号表标记符放置在与特定源函数相对应的符号表条目内。
除了用绑定位置描述显示地识别绑定位置之外,另外还可用翻译程序专用的源指令组扩展隐式地识别绑定位置,当源代码被编译时该扩展设置在该源代码内(见下文的“S-call”)。
参数变换当调用本机函数时,翻译程序19必须遵守目标结构的调用规约。作为比较,只要翻译程序19遵守在整个目标代码21中的某些一致的调用规约,则目标代码21不必需要遵守目标结构调用规约。另外,翻译程序19可能需要在源机器状态(如目标代码21内所示)和本机机器状态(如本机代码28内所示)之间进行数据变换,这两种状态均用于本机函数的输入参数以及如果有的话该函数的返回值。这种数据变换的示例可包括(i)endian转换(即字节交换);(ii)数据结构对准;(iii)源地址和目标地址之间的转换;以及(iv)值变换(例如常数转换或值缩放)。
例如,在MIPS体系结构上在寄存器内传递函数参数,而在x86结构上在堆栈上传递参数。为了使MIPS-x86翻译程序调用本机函数,x86调用规约要求将函数参数从源寄存器移到堆栈处。
图6示出翻译程序19调用本机函数执行的步骤。为了调用本机函数,翻译程序19必须执行一些步骤参数建立501;输入参数变换503;本机函数调用505;以及结果变换507。参数建立501指计算函数调用参数的值的目标代码21。输入参数变换503根据函数调用参数的目标代码21的表示将这些参数的值组织成本机函数代码希望的格式和位置。本机函数调用505是对本机函数的实际函数调用,并且包括以符合本机调用规约的方式将(重定格式的)参数组织成函数原型要求的顺序。函数原型指示函数参数的顺序和类型,以及函数返回值的类型。例如,如果本机调用规约要求在堆栈上传递自变量,则调用本机函数的目标代码21必须按正确的顺序将自变量放置在堆栈上,并使堆栈指针相应地前进。结果变换507如果有的话变换该函数的返回值;该函数返回其格式与本机体系结构一致的值,翻译程序将该值转换成目标代码21使用的表示。
参数建立501对于本机绑定机制22不是专属的,这是因为不管该函数是作为被翻译的源代码21还是本机代码28被调用,目标代码21都必须计算参数值。在翻译程序19不知道本机函数调用将使用哪个特定源寄存器(作为参数值)的情况下,翻译程序19必须校正使用的源寄存器的值,以确保源寄存器体27处于一致的状态。翻译程序优化例如惰性估计(lazy evaluation)会延迟源寄存器值的计算,直到需要这些值,其中校正是指其估计已被推迟的寄存器的强迫计算。当被校正时,源寄存器的值然后被存储在源寄存器体27内。
除了计算函数的显式参数的值(在一些情况下这需要校正所有源寄存器)之外,由于本机调用会对存储器存取的形式产生负面影响,所以参数建立步骤501还必须确保源存储器空间处于一致状态。在一个实施例内,对本机函数调用编码(不管是成为本机调用分支还是基础(underlying)本机函数)的IR校正源存储状态,从而在本机函数调用之前将源程序内的在函数调用之前发生的所有加载和存储植入目标代码内,并且同样在本机调用之前在植入函数调用之后不应发生存储器存取。
“参数变换”509用于统一指代步骤503、505和507,指的是目标代码21和本机代码28的不同数据格式和调用规约之间的各个转换的全部。执行参数变换509的代码被称为“调用分支”,其包括围绕基础本机函数调用的最小包装(wrapper),其唯一的用途是允许目标代码21调用者与本机代码28被调用者交互。因此,单个“调用分支”可分成目标代码21和本机代码28分量。参数变换509是全部在目标代码21内进行还是部分在本机代码28内进行依赖于本机绑定的实现。
本机代码分支在一些实施例中,用于本机绑定的参数变换509部分由本机代码28执行。本机代码分支的缺点是它们不能被翻译程序19优化。在这些实施例内,目标代码21执行一些参数变换,并使用本机调用规约来调用本机调用分支。该调用分支的本机代码28然后执行另外的参数变换并调用基础本机函数。
图4示出使用基于本机代码调用分支113的本机绑定的翻译程序120的说明性实施例中的函数调用的操作流程的框图。此示例内的源程序106包括源可执行程序107和多个源库,多个源库包括专用库109和系统库111。翻译程序120用对本机代码调用分支113的调用代替对源系统库函数的111的调用。调用该本机代码调用分支113的目标代码21执行参数变换。本机代码调用分支113执行另外的参数变换和参数映射。本机代码调用分支113然后调用本机系统库函数117。
本机代码分支统一接口在一个实施例内,通过定义一个统一调用分支函数接口来使本机代码参数变换509更容易。统一调用分支函数接口为所有本机调用分支以及对应的数据类型定义了一个固定的函数签名,其允许翻译程序120调用该调用分支而不需要对基础本机函数的函数签名(原型)有任何了解。这允许周高级编程语言例如C或C++来实现调用分支,这使得翻译程序19的终端用户更容易访问该本机绑定机制。
在此实施例内,将调用分支函数作为链接到翻译程序可执行程序的本机代码可执行代码进行编译。在执行期间,翻译程序120使用本机调用规约通过该统一接口调用该调用分支。由于该调用分支接口是统一的,所以对于所有本机调用而言,调用该调用分支的目标代码序列是相同的。
例如,在一个实施例内,统一调用分支接口是C函数,该函数刚好使用两个参数——调用位置的源地址以及对包含所有源寄存器值的统一数据结构的参考,并返回一个值——翻译程序应执行的下一个源指令的源地址。传递给调用分支的统一数据结构经常包含所有源寄存器的当前值,其另外被成为源上下文(context)。
在基于统一调用分支接口的本机绑定机制中,本机绑定分成几个部分(i)校正所有源寄存器值的特定IR节点类型;(ii)目标代码21,该代码将所有源寄存器编集成统一的上下文结构并根据本机调用规约调用该调用分支;以及(iii)将特定源寄存器值编集成函数参数并调用本机函数的本机调用分支。
在翻译期间,将本机调用位置翻译成本机调用IR节点。本机调用IR节点包含对所有源寄存器的IR的相关参考。本机调用IR节点的这些IR相关性可保证在目标代码生成阶段,将在本机调用之前生成对应于源寄存器值的目标代码。翻译程序优化例如惰性估计可延迟源寄存器值的计算,直到需要那些值。本机调用IR相关性告知该代码生成阶段本机调用分支“需要”所有源寄存器值。这样,翻译程序19在生成用于调用本机调用分支113的目标代码21之前,生成用于校正所有源寄存值的目标代码21。同样,为了生成代码,将本机调用IR节点看作是存储器参考,从而在目标代码21中的函数调用之前,(生成并)执行在源代码17中的函数调用之前的所有加载和存储。类似地,推迟在源代码17中的函数调用之后发生的所有加载和存储,直到进行本机调用之后。
必要时,翻译程序19可包括专用的抽象寄存器以保持该本机调用IR。在翻译的IR生成阶段,抽象寄存器用作用于IR树(即根节点)的占位符。IR树必须链接到抽象寄存器,否则该IR树不能被当做目标代码发出。在其它翻译程序内,本机调用IR代码可连接到现有的抽象寄存器例如用于(当前块的)后继地址的抽象寄存器。
调用本机调用分支113的目标代码21校正源寄存器值,并然后将它们记录在源上下文结构内。由于在此实施例内本机代码调用分支113由本机代码28执行,所以必须将源上下文构造成语本机结构一致的表示。这样,目标代码21在必要时执行参数变换503以将源寄存器值从目标代码表示转换成本机代码表示。将多个值转换成与另一体系结构一致的数据结构表示的进程有时被称为信号编集。
目标代码21构成包含所有源寄存器值的本机表示的源上下文。然后,目标代码21调用本机代码调用分支113,将源上下文作为参数传递给该本机代码调用分支。该调用分支113调用该基础本机函数,从源上下文中提取出所需的特定的源寄存器,并将它们作为合适的参数传递给本机函数。调用分支113从而对本机函数的原型编码,并定义特定的源寄存器到对应的本机函数参数的映射。
在一些情况下,本机函数接口可与其源代码等效物大大不同,从而必须对源数据执行另外的计算(除用于数据表示和调用规约的变换之外的),以使源数据适于用作源函数参数。在此情况下,调用分支113对源寄存器值执行另外的参数变换。例如,本机函数可期望一个与其源代码等效物不同的特定参数。在此情况下,调用分支113在调用本机函数之前对合适的源寄存器值执行常量转换,以说明该参数的单元类型中的不同。
在使用统一的本机调用分支接口的实施例中,目标代码21不加区别地将所有源寄存器从目标代码表示变换成本机代码表示。本机调用分支113然后提取本机函数的原型需要作为参数的特定(变换的)源寄存器。本机函数分支113还可执行另外的参数变换,以反映被调用的函数的源版本和本机版本之间的区别。目标代码21调节目标代码21和本机代码28之间的表示差别,而调用分支113说明特定的基础本机函数的签名。
在此实施例内,本机绑定绑定位置描述识别将绑定的源函数和对应的本机调用分支函数,而对基础的将绑定的源函数的识别在该调用分支实现中是隐式的(即被硬编码)。
本机代码分支编译脚本在另一实施例内,本机代码参数变换使用专用的本机绑定编程语言(下文被称为“脚本语言”)实现。在执行之前或在执行期间,翻译程序19分析调用分支的脚本语言实现,并将其编译成可本机执行的模块。调用分支模块然后与翻译程序可执行程序链接,并如上所述地使用本机调用规约调用(本机)调用分支函数。
将本机绑定脚本编译或解释成调用分支的可执行的表示。在一个实施例内,在翻译程序执行之前,使用单独的工具将绑定位置描述解释成可执行的本机代码。在另一个实施例内,翻译程序本身在运行时将绑定位置描述解释或编译成可执行的本机代码或翻译程序IR(下文被生成为目标代码)。
在一些实施例中,脚本语言是翻译程序专用的专用语言。该脚本语言包括说明宽范围的可能的参数变换操作的原语(编程语言程序块),其包括(i)数据类型的描述;(ii)目标代码和那些数据类型的本机表示之间的转换;(iii)本机函数的识别;(iv)将特定的源寄存器映射到特定的函数参数;(v)对源程序的存储空间的存储器访问;和(vi)基本数学操作。在可选择实施例内,脚本语言还包括(vi)基本逻辑操作和(vii)多个本机绑定脚本之间的临时值的全局存储。这些原语的实现(即使用翻译程序或专用工具从脚本生成的本机代码)必须与目标体系结构的表示和调用规约一致。
在此实施例内,本机绑定绑定位置描述识别将绑定的源函数和对应的本机调用分支函数,同时对基础的将绑定的源函数的识别在该调用分支的脚本语言实现中被硬编码。
目标代码分支在另一实施例内,用于本机绑定的参数变换完全以目标代码执行。在此实施例内,翻译程序19在译码时检测到本机绑定调用,并将参数变换编码成IR树(最终生成为目标代码)。通过在IR中表示本机函数原型的参数变换和细节,调用本机代码容入源代码(调用分支的IR与源代码的IR不能区分)。这使得翻译程序可对参数变换代码进行优化(例如按组分块)。相反,在本机代码内执行的参数变换例如在本机代码调用分支内执行的源寄存器到函数参数的映射(上文所述)在翻译程序的外部进行,并且不能被优化。
图5示出使用基于目标代码调用分支115的本机绑定的翻译程序122的说明性实施例中的函数调用的操作流程的框图。源程序106包括源可执行程序107和多个源库,多个源库包括专用库109和系统库111。翻译程序122用对目标代码调用分支115的调用代替对源系统库函数111的调用。目标代码调用分支115执行参数变换和参数映射,然后调用本机系统库117中的函数。
在使用目标代码调用分支115的翻译程序122的实施例中,其中目标代码21直接调用被绑定的本机函数,所有参数变换和参数映射都由目标代码21执行。在这些实施例内,目标代码21说明表示变换以及特定本机函数的签名(即特定源寄存器到对应的本机函数参数的映射)。为了使目标代码21执行参数映射,翻译程序122在翻译期间必须知道本机函数原型以及源寄存器到参数的映射。在一些情况下,目标代码调用分支115在与调用该分支的目标代码21(“调用者目标代码”)分开的块内被翻译。在其它情况下,目标代码调用分支115在与调用该分支的目标代码21相同的块内被翻译,这样该目标代码调用分支可集成入该调用者目标代码并与该调用者目标代码一起优化,这被称为“早期绑定”机制。在源程序从许多调用位置调用特定的源函数的情况下,在每个调用位置内联目标代码调用分支115是不利的,这是因为导致的调用分支代码的复制会消耗过多的存储器。在这种情况下,翻译程序122将目标代码调用分支115保持为单独的块,每个翻译的调用位置可调用该块,而不是在每个调用位置内联该调用分支。本机绑定的一种优化是仅在非常频繁地执行的块内使用早期绑定(即内联调用分支)。
目标代码分支Schizo调用在另一实施例内,翻译程序19使用被称为Schizo调用或“S-call”的机制,其中通过将源指令组扩展到包括翻译程序专用的本机绑定指令(被称为S-Call命令)来促进目标代码参数变换,在编译该源代码时将该本机绑定指令插入该源代码。当翻译程序19将该源代码解码时,其检测和解释这些S-Call命令,并植入合适的执行参数变换的IR(或目标代码)。
该S-Call机制需要源程序的开发者的支持。当编译源程序时,在编译的源程序内将S-Call命令编码成源指令。描述对本机函数的调用的调用分支并不仅局限于包含S-Call命令,它们可包括可帮助参数变换的常规的、合法的源指令。在组合时,S-Call命令和常规的源指令对参数变换所需的所有信息和操作进行编码。
在一个实施例内,将S-Call命令编码成由多个子部分构成的长度可变的指令,从而S-Call命令指令可大于常规的源代码指令,甚至可以是多个常规的源指令的大小。S-Call命令以识别该指令为S-Call命令的子部分开始,该子部分已知将在源结构上被解释成非法指令,被称为Schizo Escape。Schizo Escape子部分可任选地还识别S-Call命令内包含的命令的类型。S-Call命令优选地分成五种命令类型(1)标记符,(2)参数,(3)调用,(4)复制和(5)废弃。S-Call命令的类别被编码成前端的Schizo Escape子部分的未用位。SchizoEscape之后是类别专用的选项和/或自变量的组合,其中的每一个均具有预定的操作码和格式,并且每一个均在S-Call命令指令中被编码成一个或多个字(即四字节的单元)。S-Call命令指令以作为开始的Schizo Escape的重复的子部分结束。下面将详细说明上述五种S-Call命令,但是应理解,本发明的发明人的全部意图是除了上述五类之外,其它类型的翻译程序专用的本机绑定指令也可用作S-Call命令。
S-Call“标记符”命令是用于允许应用程序二进制接口(ABI)专用优化的任选标记符。S-Call标记符命令指示包含翻译程序专用代码(例如调节分支到本机函数)的源代码17的范围(起始和结束地址),其可以与源函数的全部范围重合或不重合。S-Call标记符命令有两类起始和结束。S-Call标记符命令具有一字符串自变量,其为被标记的位置指定名称(即被绑定的源函数的名称)。
S-Call“参数”命令识别一将用作本机函数参数的值,并对该值进行合适的参数变换。在一个实施例内,每个S-Call参数命令通过将对应的值推入堆栈,并因此要求S-Call参数处于与函数原型相对应的顺序,定义了函数调用的“下一个”参数。
S-Call“调用”命令将对本机函数的实际函数调用编码。S-Call调用命令自变量包括存储函数的返回值的位置或名称、绝对地址或者地址在被调用的函数的源机器状态中的位置。
S-Call“复制”命令对向或从源寄存器或源存储位置复制值并执行目标代码和本机表示之间的变换的操作进行编码。
S-Call“废除”命令使它们之前的指令无效。如下文所述,该命令与无条件的分支一起使用以允许源程序在本机运行时可正确执行,同时仍允许翻译程序识别和解释代码的翻译程序专用部分。
在翻译期间,翻译程序19检测Schizo Escape,并将S-Call命令解码成对应的参数变换和本机函数调用操作的IR表示。翻译程序19将参数变换IR组合成当前块的IR森林,其然后生成为目标代码。将参数变换操作编码成IR允许参数变换代码并入将源代码编码的IR并与其一起优化。
由于S-Call命令是翻译程序专用的本机绑定指令,所以使用只有翻译程序19理解的起始指令操作码——Schizo Escape——在源程序中对S-Call命令编码。源处理器将S-Call命令解释成非法的源指令。这样,当源程序本机(即在目标体系结构上)运行时必须避免执行S-Call命令。源程序软件开发商可使用多种方法来允许S-Call增强的源程序本机运行,包括(a)条件执行和(b)分支预先分析。条件执行包括条件源代码,该代码根据运行时环境检查源程序是本机运行还是作为被翻译的程序运行,并且如果本机运行则跳过S-Call命令。分支预先分析包括植入源代码内的跳过所有翻译程序专用的指令(例如但不局限于S-Call命令)的无条件分支指令。当本机运行时,无条件分支由此跳过该翻译程序专用代码执行。当作为被翻译的程序运行时,翻译程序忽视所有无条件分支指令,在该无条件分支指令之后为S-Call废除命令(即无条件分支是翻译程序用于在解码时识别翻译程序专用代码的源指令模式的一部分)。
目标代码分支外部Schizo分支在另一实施例内,由Schizo-call命令和普通的源指令构成的调用分支位于源代码的被单独编译的单元内。翻译程序19使用专用的本机绑定绑定位置描述语言(如上所述)将源代码位置指定为绑定位置。当翻译程序19到达这样的绑定位置时,转移控制流以代替地执行外部Schizo分支。从此位置向外,翻译程序的行为与为Schizo调用而描述的行为相同。当不能将S-Call命令直接插入源代码时(例如,当用于源库/应用程序的源代码不可用时),外部Schizo分支允许使用S-Call命令。
目标代码分支解释脚本在可选择实施例内,使用上述的专用的本机绑定实现语言(“脚本语言”)来使目标代码参数变换更容易。在此实施例内,在运行时,翻译程序将本机绑定脚本解释成参数变换的IR表示。该翻译程序将参数变化IR组合成当前块的IR森林,其随后作为被优化并生成为目标代码。这种翻译程序必须包含可对脚本语言进行分析和解码的前端部分。
在此实施例内,本机绑定绑定位置描述识别将绑定的源函数以及对应的本机调用分支函数,而对将绑定的基础本机函数的识别在调用分支的实现中硬编码。
目标代码分支统一接口在可选择实施例内,如上所述,通过定义统一调用分支函数接口来使目标代码参数变换更容易。统一调用分支函数接口为所有本机调用分支以及对应的数据类型定义了一个固定的函数签名,其允许翻译程序调用该调用分支作为本机函数,而不需要对基础本机函数的函数签名(原型)有任何了解。这允许用高级编程序言例如C或C++来实现调用分支,这使得翻译程序的终端用户更容易访问该本机绑定机制。
与上述的本机代码的统一调用分支接口相反,在一些实施例内,翻译程序在运行时分析调用分支实现,并将其解释成参数变换的IR表示。换句话说,翻译程序将调用分支实现编译成翻译程序IR。翻译程序将参数变化IR组合成当前块的IR森林,其随后作为被优化并生成为目标代码。与编译器类似,这种翻译程序必须包含可对脚本语言进行分析和解码的前端部分。
在此实施例内,本机绑定描述识别将绑定的源函数以及对应的本机调用分支函数,而对将绑定的基础本机函数的识别在调用分支的实现中硬编码。
尽管已示出和说明一些优选实施例,但是本领域内的技术人员应理解,可实现多种改变和修改而不会背离被所附权利要求定义的本发明的范围。
注意与关于此申请的本说明书同时或在其之前申请的且对公众公开以便能检查此说明书的所有论文和文献,所有这些论文和文献的内容在此引入作为参考。
除了其中这样的特征和/或步骤中的至少一些相互排斥的组合之外,本说明书(包括任一权利要求、摘要和附图)内公开的所有特征和/或所公开的任何方法或进程的所有步骤可以任何方式组合。
本说明书(包括任何权利要求、摘要和附图)内公开的每个特征可被起到相同、等效或类似作用的可选择的特征代替,除非另外明确说明。因此,除非另外明确说明,公开的每个特征仅是等效或类似特征的一般系列的一个示例。
本发明并不局限于前述的实施例的细节。本发明可扩展到本说明书(包括任何所附权利要求、摘要和附图)内公开的特征中的任何新颖的特征或任何新颖的组合,或者所公开的任何方法或进程的步骤中的任何新颖的步骤或任何新颖的组合。
权利要求
1.一种在从可由源处理器执行的源程序代码(17)翻译到可由目标处理器(13)执行的目标程序代码(21)期间执行本机绑定以执行本机代码(28)的方法,其中本机代码(28)是可由目标处理器(13)执行的代码,所述方法包括识别具有对应本机代码(28)的特定源程序代码(17);识别对应于该被识别的源程序代码(17)的本机代码(28);及执行对应的本机代码(28)而不是执行该被识别的源程序代码(17)的翻译版本。
2.根据权利要求1的方法,其特征在于,该识别的源程序代码(17)对应于源函数(109),该识别的本机代码(28)对应于本机函数(117),其中该本机代码(28)执行步骤包括在源程序代码(17)的翻译过程中执行本机函数(117)而不是源函数(109)。
3.根据权利要求2的方法,其特征在于,该本机函数(117)执行步骤包括将零个或更多函数参数从目标代码表示变换成本机代码(28)表示;根据本机函数(117)的原型调用具有该变换的函数参数的本机函数(117);以及将该调用的本机函数(117)的零个或更多返回值从本机代码(28)表示变换到目标代码表示。
4.根据权利要求3的方法,其特征在于,该变换步骤中的至少一个变换生成该变换的中间表示。
5.根据权利要求3或4的方法,其特征在于,该变换步骤中的至少一个变换生成目标代码。
6.根据权利要求3、4或5的方法,其特征在于,本机函数(117)执行步骤还包括将目标代码内的所有源寄存器值从目标代码表示变换成本机代码(28)表示;根据统一调用分支接口从目标代码中调用具有该变换的源寄存器的本机代码(28)调用分支函数;根据本机函数(117)的原型从本机代码(28)调用分支函数中调用具有特定源寄存器和/或参数堆栈的本机函数(117)。
7.根据权利要求3到6中的任何一个的方法,其特征在于,该本机函数(117)执行步骤包括将函数参数从目标代码表示变换成本机代码(28)表示;根据本机函数(117)的原型调用具有变换的函数参数的本机函数(117);及将该调用的本机函数(117)的结果从本机代码(28)表示变换成目标代码表示。
8.根据权利要求3到7中的任何一个的方法,其特征在于,通过添加到源指令组的翻译程序专用指令以源代码描述函数参数变换步骤和本机函数(117)调用步骤。
9.根据前面任何一个权利要求的方法,其特征在于,使用绑定位置描述执行识别特定源代码及其对应的本机代码(28)的步骤。
10.根据权利要求9的方法,其特征在于,该绑定位置描述包括源函数(109)和本机函数(117),其中源函数(109)识别具有对应的本机代码(28)的特定的源程序代码(17),本机函数(117)识别对应的本机代码(28)。
11.根据权利要求10的方法,其特征在于,该方法还包括当遇到绑定位置描述中包含的源函数(109)时,在目标代码内插入在该源代码的翻译期间对本机函数(117)的调用分支。
12.根据权利要求9、10或11的方法,其特征在于,该绑定位置描述嵌入在执行该翻译的翻译程序内。
13.根据权利要求9到12中的任何一个的方法,其特征在于,该方法还包括在翻译执行开始时,从存储的绑定位置描述文件中读取绑定位置描述。
14.根据权利要求9到13中的任何一个的方法,其特征在于,绑定位置描述包括该源代码内的位置和对应的本机函数(117),其中该源代码内的位置识别具有对应的本机代码(28)的特定的源程序代码(17),该本机函数(117)识别对应的本机代码(28)。
15.根据权利要求9到14中的任何一个的方法,其特征在于,绑定位置描述包括该源代码内的位置和对将被调用的代码的参考,其中该源代码内的位置识别具有对应的本机代码(28)的特定的源程序代码(17),对将被调用的代码的参考识别对应的本机代码(28)。
16.根据权利要求15的方法,其特征在于,将被调用的代码是目标代码。
17.根据权利要求9到16中的任何一个的方法,其特征在于,该绑定位置描述包括在源函数(109)调用之前、之后或代替该源函数(109)调用插入该目标代码中的本机函数(117)调用。
18.根据权利要求9到17中的任何一个的方法,其特征在于,该方法还执行运行时符号修补,该运行时符号修补包括在源程序的符号表内对源到本机函数(117)映射编码,用专用的本机绑定标记符代替该源程序的符号表内的条目,以及将在翻译期间遇到的专用的本机绑定标记符解释成绑定位置描述以指示将调用的合适的本机函数(117)。
19.根据权利要求9到18中的任何一个的方法,其特征在于,该绑定位置描述包括与外部Schizo调用命令的对应关系,其中Schizo调用命令是翻译程序专用的本机绑定指令,该方法包括当在源代码翻译期间遇到识别外部Schizo调用命令的绑定位置描述时,将翻译流转向外部Schizo调用命令的执行。
20.根据权利要求19的方法,其特征在于,该外部Schizo调用命令执行步骤包括解释外部Schizo调用命令;以及生成外部Schizo调用命令的中间表示,这一步骤将函数参数从目标代码表示变换成本机代码(28)表示,以及根据本机函数(117)的原型调用具有该变换的函数参数的本机函数(117)。
21.根据权利要求19的方法,其特征在于,该外部Schizo调用命令执行步骤包括解释外部Schizo调用命令;以及生成用于该外部Schizo调用命令的目标代码,这一步骤将函数参数从目标代码表示变换成本机代码(28)表示,以及根据本机函数(117)的原型调用具有该变换的函数参数的本机函数(117)。
22.根据前面任何一个权利要求的方法,其特征在于,该方法还包括将Schizo调用命令插入源代码,其中Schizo调用命令是翻译程序专用的本机绑定指令;以及在源代码的翻译期间检测Schizo调用命令。
23.根据权利要求22的方法,其特征在于,该方法还包括当在源代码的翻译期间遇到Schizo调用命令时,将翻译流转向该外部Schizo调用命令的执行。
24.根据权利要求23的方法,其特征在于,该Schizo调用命令执行步骤包括解释外部Schizo调用命令;以及生成该Schizo调用命令的中间表示,这一步骤将函数参数从目标代码表示变换成本机代码(28)表示,以及根据本机函数(117)的原型调用具有该变换的函数参数的本机函数(117)。
25.根据权利要求23的方法,其特征在于,该Schizo调用命令执行步骤包括解释该Schizo调用命令;以及生成用于该Schizo调用命令的目标代码,这一步骤将函数参数从目标代码表示变换成本机代码(28)表示,以及根据本机函数(117)的原型调用具有该变换的函数参数的本机函数(117)。
26.根据权利要求22到25中的任何一个的方法,其特征在于,该Schizo调用命令是包括多个子部分指令的可变长度的指令。
27.根据权利要求26的方法,其特征在于,该多个子部分指令包括Schizo Escape子部分指令,所述Schizo调用命令检测步骤还包括检测该Schizo Escape子部分指令。
28.根据权利要求27的方法,其特征在于,所述Schizo Escape子部分指令还识别由该Schizo调用命令的其它子部分指令表示的Schizo调用命令的类型。
29.根据前面任何一个权利要求的方法,其特征在于,该方法还包括分析和解码包含本机绑定脚本的本机绑定实现描述语言;在翻译期间解释该本机绑定脚本;以及生成本机绑定脚本的中间表示以将函数参数从目标代码表示变换成本机代码(28)表示。
30.根据权利要求29的方法,其特征在于,该方法还包括将该本机绑定脚本的中间表示集成到用于源代码块的中间表示森林;以及生成用于该中间表示森林的目标代码。
31.根据前面任何一个权利要求的方法,其特征在于,该方法还包括将目标代码中的所有源寄存器值从目标代码表示变换成本机代码(28)表示;根据统一调用分支接口从目标代码中调用具有该变换的源寄存器的本机代码(28)调用分支函数;解释本机代码(28)调用分支函数;以及生成本机代码(28)调用分支函数绑定脚本的中间表示以将函数参数从目标代码表示变换成本机代码(28)表示。
32.根据权利要求21或任何一个从属于权利要求21的权利要求的方法,其特征在于,该方法还包括将本机代码(28)调用分支函数的中间表示集成到用于源代码块的中间表示森林中;以及生成用于该中间表示森林的目标代码。
33.根据权利要求3或任何一个从属于权利要求3的权利要求的方法,其特征在于,该本机函数(117)执行步骤还包括将目标代码中的所有源寄存器值从目标代码表示变换成本机代码(28)表示;从目标代码中调用具有该变换的源寄存器的本机代码(28)调用分支函数;根据本机函数(117)的原型从本机代码(28)调用分支函数中调用具有特定源寄存器和/或参数堆栈的本机函数(117)。
34.根据前面任何一个权利要求的方法,其特征在于,该方法还包括分析本机代码(28)调用分支函数的脚本语言实现;将分析后的本机代码(28)调用分支函数编译成本机代码(28)可执行模块;以及将本机代码(28)可执行模块与用于执行翻译的可执行程序相链接。
35.根据权利要求34的方法,其特征在于,该本机代码(28)可执行模块可执行将目标代码中的所有源寄存器值从目标代码表示变换成本机代码(28)表示;从目标代码中调用具有变换的源寄存器的本机代码(28)调用分支函数;根据本机函数(117)的原型从本机代码(28)调用分支函数中调用具有特定源寄存器和/或参数堆栈的本机函数(117)。
36.根据权利要求34或35的方法,其特征在于,该识别特定源代码及其对应的本机代码(28)的步骤使用绑定位置描述执行,所述绑定位置描述包括源函数(109)和本机代码(28)调用分支函数,其中该源函数(109)识别具有对应本机代码(28)的特定源程序代码(17),本机代码(28)调用分支函数识别对应的本机代码(28)。
37.根据权利要求36的方法,其特征在于,该方法还包括在本机代码(28)可执行模块的脚本语言实现中对本机代码(28)调用分支函数的本机函数(117)的标识进行编码。
38.根据权利要求3或任何一个从属于权利要求3的权利要求的方法,其特征在于,该本机函数(117)执行步骤还包括将目标代码中的所有源寄存器值从目标代码表示变换成本机代码(28)表示;从目标代码中调用具有变换的源寄存器的目标代码调用分支函数;根据本机函数(117)的原型从目标代码调用分支函数中调用具有特定源寄存器和/或参数堆栈的本机函数(117)。
39.根据权利要求38的方法,其特征在于,该方法还包括生成本机函数(117)执行步骤的中间表示;将本机函数(117)执行步骤的中间表示集成到用于源代码块的中间表示森林中;以及生成用于该中间表示森林的目标代码。
40.根据前面任何一个权利要求的方法,其特征在于,将执行的源函数(109)是系统调用。
41.根据前面任何一个权利要求的方法,其特征在于,将执行的源函数(109)是库函数。
42.一种计算机可读存储媒体,该媒体上驻留可由计算机执行以实现根据权利要求1到41中的任何一个的方法的计算机可读代码形式的软件。
43.一种组合,包括目标处理器(13);以及用于执行根据权利要求1到41中的任何一个的方法的翻译程序代码。
全文摘要
提供一种本机绑定技术,用于在源代码到目标代码的翻译期间插入对本机函数的调用,从而源程序中的对源代码函数的函数调用在目标代码中被对相同函数的本机等效物的调用代替。将本机函数(117)调用的参数从目标代码表示变换成与本机代码(28)表示、本机代码(28)调用规约以及本机函数(117)原型一致。
文档编号G06F9/455GK1823323SQ200480020102
公开日2006年8月23日 申请日期2004年7月13日 优先权日2003年7月15日
发明者亚力克斯·布朗, 杰兰特·诺斯, 富兰克·托马斯·维格尔, 加雷斯·安东尼·奈特 申请人:可递有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1