CN200910005718.9
2009.02.03
CN101520737A
2009.09.02
授权
有权
授权|||实质审查的生效IPC(主分类):G06F 9/45申请日:20090203|||公开
G06F9/45; G06F11/36
G06F9/45
三星电子株式会社
金泰松; 金泓锡; 白昌祐
韩国京畿道水原市
2008.2.27 KR 10-2008-0017957
北京铭硕知识产权代理有限公司
郭鸿禧;邱 玲
提供了一种编译方法和使用该编译方法的处理器。所述方法包括:对包括至少一个第一操作命令的第一程序代码进行仿真,以产生第一操作结果;对第一程序代码进行编译,以产生包括至少一个第二操作命令的第二程序代码;对第二程序代码进行仿真,以产生第二操作结果;将第一操作结果与第二操作结果进行比较,以验证第二程序代码是否有效。
1、 一种编译方法,所述方法包括:对包括至少一个第一操作命令的第一程序代码进行仿真,以产生第一操作结果;对所述第一程序代码进行编译,以产生包括至少一个第二操作命令的第二程序代码;对所述第二程序代码进行仿真,以产生第二操作结果;将所述第一操作结果与所述第二操作结果进行比较,以验证所述第二程序代码是否有效。2、 如权利要求1所述的方法,其中:对所述第一程序代码进行编译的步骤包括:向所述至少一个第一操作命令分配操作标识符,将所述第一操作结果与所述第二操作结果进行比较的步骤包括:将所述至少一个第一操作命令中的每一个的操作结果与所述至少一个第二操作命令之一的操作结果进行比较,其中,所述至少一个第二操作命令之一与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。3、 如权利要求1所述的方法,其中,将所述第一操作结果与所述第二操作结果进行比较的步骤不对所述第二操作命令的操作结果进行验证,其中,所述第二操作命令不具有分配给所述至少一个第一操作命令中的每一个的操作标识符中相应操作标识符。4、 如权利要求1所述的方法,其中,将所述第一操作结果与所述第二操作结果进行比较的步骤不对不具有所述第二操作命令的第一操作命令的操作结果进行验证,其中,所述第二操作命令与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。5、 如权利要求1所述的方法,其中,对所述第一程序代码进行编译的步骤包括:基于执行所述第一操作代码的处理器的并行性来调度所述第一程序代码。6、 如权利要求1所述的方法,其中,对所述第一程序代码进行编译的步骤包括:对所述第一程序代码进行寄存器分配,以使当执行所述第一程序代码时同时活跃的寄存器的数量不超过硬件支持的寄存器的数量。7、 如权利要求1所述的方法,其中,对所述第一程序代码进行仿真的步骤包括:通过参照在对所述第一程序代码进行寄存器分配之后产生的第二程序代码的堆栈信息来对所述第一程序代码进行仿真。8、 一种存储有用于实现一种编译方法的程序的计算机可读存储介质,所述程序包括使计算机执行如下操作的指令:对包括至少一个第一操作命令的第一程序代码进行仿真,以产生第一操作结果;对所述第一程序代码进行编译,以产生包括至少一个第二操作命令的第二程序代码;对所述第二程序代码进行仿真,以产生第二操作结果;将所述第一操作结果与所述第二操作结果进行比较,以验证所述第二程序代码是否有效。9、 一种处理器,包括:代码变换器,对包括至少一个第一操作命令的第一程序代码编译,以产生包括至少一个第二操作命令的第二程序代码;第一仿真器,对所述第一程序代码进行仿真,以产生第一操作结果;第二仿真器,对所述第二程序代码进行仿真,以产生第二操作结果,其中,处理器通过将所述第一操作结果与所述第二操作结果进行比较来验证所述第二程序代码是否有效。10、 如权利要求9所述的处理器,其中:所述代码变换器向所述至少一个第一操作命令分配操作标识符,所述处理器将所述至少一个第一操作命令中的每一个的操作结果与所述至少一个第二操作命令之一的操作结果进行比较,其中,所述至少一个第二操作命令之一与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。11、 如权利要求9所述的处理器,其中,所述代码变换器对所述第一程序代码进行寄存器分配,以使当执行所述第一程序代码时同时活跃的寄存器的数量不超过硬件支持的寄存器的数量。12、 如权利要求11所述的处理器,其中,所述代码变换器发送在对所述第一程序代码进行寄存器分配之后产生的第二程序代码的堆栈信息,并且所述第一仿真器通过参照所述堆栈信息来对所述第一程序代码进行仿真。13、 如权利要求9所述的处理器,其中,所述处理器是具有多个功能单元并且根据将被执行的操作命令并行使用所述多个功能单元的可重构处理器。
编译方法和使用该编译方法的处理器 本申请要求于2008年2月27日在韩国知识产权局提交的第10-2008-0017957号韩国专利申请的利益,该申请完全公开于此以资参考。 技术领域 下面的描述涉及编译器,更具体地讲,涉及一种用于编译程序代码的方法和使用该方法的处理器。 背景技术 通常,编译器将以编程语言(例如,公式转换器(Fortran)、C、C++(CPP)等)描述的程序代码转换成将在处理器中执行的适当的命令。可将编译器的操作分成前端、机器无关的转换、机器相关的转换等。 前端操作将用编程语言描述的程序代码转换成可被编译器容易处理的中间表示(IR)。机器相关的转换还被称为后端操作,该操作可能容易受执行程序代码的处理器的配置的影响。 由于每开发或升级一次处理器就可使用新的算法或者更新一次算法,所以需要针对后端操作开发或升级新的编译器。 在最新开发或升级编译器的情况下,编译器开发者可能就需要验证编译器的正确性。验证编译器的操作被称为“调试编译器”。由于在后端操作期间转换的代码是机器友好代码,所以本领域的普通技术人员可能难以通过观测编译操作来验证编译器的正确性。 另外,可对调试编译器使用基于正常原理的认证方案。然而,尽管认证方案可以基于数学模型的理论正确地验证编译器,但由于认证方案的复杂性导致认证方案难以实现。 发明内容 在一个总的方面,提供了一种对编译器的有效性进行验证的新的编译方法。 在另一总的方面,提供了一种对可重构处理器中使用的编译器的有效性进行验证的编译方法。 在另一总的方面,一种编译方法包括:对包括至少一个第一操作命令的第一程序代码进行仿真,以产生第一操作结果;对第一程序代码进行编译,以产生包括至少一个第二操作命令的第二程序代码;对第二程序代码进行仿真,以产生第二操作结果;将第一操作结果与第二操作结果进行比较,以验证第二程序代码是否有效。 对第一程序代码进行编译的步骤可包括:向所述至少一个第一操作命令分配操作标识符,将第一操作结果与第二操作结果进行比较的步骤可包括:将所述至少一个第一操作命令中的每一个的操作结果与所述至少一个第二操作命令之一的操作结果进行比较,其中,所述至少一个第二操作命令之一与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。 将第一操作结果与第二操作结果进行比较的步骤可以不对第二操作命令的操作结果进行验证,其中,所述第二操作命令不具有分配给所述至少一个第一操作命令中的每一个的操作标识符中相应操作标识符。 将第一操作结果与第二操作结果进行比较的步骤可以不对不具有第二操作命令的第一操作命令的操作结果进行验证,其中,所述第二操作命令与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。 对第一程序代码进行编译的步骤可包括:基于执行第一操作代码的处理器的并行性来调度第一程序代码。 对第一程序代码进行编译的步骤可包括:对第一程序代码进行寄存器分配,以使当执行第一程序代码时同时活跃的寄存器的数量不超过硬件支持的寄存器的数量。 对第一程序代码进行仿真的步骤可包括:通过参照在对第一程序代码进行寄存器分配之后产生的第二程序代码的堆栈信息来对第一程序代码进行仿真。 在另一总的方面,一种处理器包括:代码变换器,对包括至少一个第一操作命令的第一程序代码编译,以产生包括至少一个第二操作命令的第二程序代码;第一仿真器,对第一程序代码进行仿真,以产生第一操作结果;第二仿真器,对第二程序代码进行仿真,以产生第二操作结果,其中,处理器通过将第一操作结果与第二操作结果进行比较来验证第二程序代码是否有效。 代码变换器可向所述至少一个第一操作命令分配操作标识符。 处理器可以是具有多个功能单元并且根据将被执行的操作命令并行使用所述多个功能单元的可重构处理器。 处理器可将所述至少一个第一操作命令中的每一个的操作结果与所述至少一个第二操作命令之一的操作结果进行比较,其中,所述至少一个第二操作命令之一与分配给所述至少一个第一操作命令中的每一个的操作标识符相应。 代码变换器可对第一程序代码进行寄存器分配,以使当执行第一程序代码时同时活跃的寄存器的数量不超过硬件支持的寄存器的数量。 代码变换器可发送在对第一程序代码进行寄存器分配之后产生的第二程序代码的堆栈信息,并且第一仿真器可通过参照所述堆栈信息来对第一程序代码进行仿真。 对本领域的技术人员而言,从下面详细的描述其他方面将变得清楚,其中,下面详细的描述结合附图公开了本发明的示例性实施例。 附图说明 图1是示出根据示例性实施例的编译方法的流程图。 图2是示出图1的S120的示例性操作的流程图。 图3是示出根据示例性实施例的在编译之前的程序代码的示图。 图4是示出根据示例性实施例的图3的程序代码中使用的寄存器的活性(liveness)的示图。 图5是示出根据示例性实施例的图4的寄存器之间的冲突的示图。 图6是示出根据示例性实施例的图3的编译的程序代码的示图。 图7是示出根据示例性实施例的图6的程序代码中使用的寄存器的活性的示图。 图8是示出根据示例性实施例的图7的寄存器之间的冲突的示图。 图9是示出根据示例性实施例的在图6的程序代码被寄存器分配之后的程序代码的示图。 图10是示出根据示例性实施例的编译器和该编译器的调试方法的示图。 图11是示出根据示例性实施例的处理器的示图。 贯穿附图和详细的描述,除非另有说明,否则相同的标号应被理解为表示相同的部件、特征和结构。为了清晰和方便,所述部件可能被夸大。 具体实施方式 提供了下面详细的描述以有助于读者获得对这里描述的介质、设备、方法和/或系统的全面理解。因此,将向本领域的普通技术人员提出这里描述的系统、方法、设备和/或介质的各种变化、修改和等同物。另外,省略了对已知功能和结构的描述,以增强清晰和简要。 可用硬件或软件来实现执行预定操作的装置。将用于控制网络接口的网络控制器嵌入计算机芯片,网络控制器只可执行在工厂制造网络控制器时定义的预定网络接口功能。在使用硬件的装置的情况下,可能无法在制造网络控制器之后改变网络控制器功能。在使用软件的装置的情况下,用户可对期望的程序编程,并在通用处理器中执行所述期望的程序以满足用户的需求。在使用软件的装置的情况下,可在工厂制造了原始硬件之后通过改变软件来添加新功能。尽管可通过使用软件的装置来执行各种功能,但在给定硬件中,与使用硬件的装置相比,性能可能恶化。 因此,提供了可重构处理器体系结构。可定制可重构处理器体系结构以在制造装置之后解决特定问题。处理器体系结构还可采用在空间上定制的计算来执行计算。 可通过使用能够并行处理多个命令的处理器核和粗粒度阵列(CGA,coarse grained array)来实现可重构的处理器的体系结构。 机器语言包括“1”和“0”,并在处理器中被执行。由于用户可能不适合处理机器语言,所以用户可通过使用用户容易处理的高级编程语言或通过与将“1”和“0”的组合与预定义的字相对应而产生的汇编语言来对程序代码编程。 编译器将用户容易处理的编程命令(例如,C语言、公式转换器(Fortran)、PASCAL和C++(CPP))转换成适合在处理器中执行的命令。在编译器的转换操作中,由于基于硬件信息执行后端操作,所以相关的后端操作是复杂的。 由于可在可重构处理器中改变硬件信息,并可定义用于配置可重构处理器的多个功能单元之间的关系,所以可重构处理器的后端编译操作是复杂的。 验证是否无差错地转换程序代码、检测存在错误时出现的错误、并改正检测到的错误的操作可被称为“调试”。这里提供了可适合于在可重构处理器中采用的编译器的动态调试方法。另外,依据实施例,这里提供了应用所述动态调试方法的合适的编译方法。 根据示例性实施例的编译器的编译方法或调试方法可基于经相同的仿真与编译之后的程序代码相比编译之前的程序代码是否提供相同的结果来验证编译器的正确性。 这里公开的特定实施例可提供能够逐点检查编译之前的程序代码和编译之后的程序代码的仿真结果的编译器的编译方法或调试方法。 图1示出示例性的编译方法。 参照图1,在操作S110,编译方法对第一程序代码进行仿真以产生第一操作结果。 第一程序代码可包括至少一个第一操作命令。可关于所述至少一个第一操作命令中的每一个产生第一操作结果。 在操作S120,编译方法对第一程序代码进行编译,以产生第二程序代码。 第二程序代码可包括至少一个第二操作命令。所述至少一个第二操作命令的数量可与所述至少一个第一操作命令的数量相同,或者不同。在操作S120,例如,经代码选择、寄存器分配、死代码去除和调度方案来对第一程序代码进行编译。 在操作S130,编译方法对第二程序代码进行仿真,以产生第二操作结果。可关于第二操作命令中的每一个产生第二操作结果。 在操作S140,编译方法将第一操作结果与第二操作结果进行比较,以验证第二程序代码是否有效。 图2示出图1的S120的示例性操作。 参照图2,在操作S210,编译方法可向第一程序代码的至少一个第一操作命令中的每一个分配操作标识符(ID)。 在操作S220,编译方法基于分配的操作ID对第一程序代码进行编译。 在这种情况下,在图1的操作S140中,可将所述至少一个第一操作命令的第一操作结果和与第一操作命令的相同操作ID相应的至少一个第二操作命令的第二操作结果进行比较。 例如,在第一程序代码中,将分配了操作ID“1”的至少一个第一操作命令的第一操作结果与具有操作ID“1”的至少一个第二操作命令的第二操作结果进行比较。 在操作命令中,其结果值既不被后来的操作命令使用也不提供最终结果的操作命令可被称为“死代码”。编译方法可基于操作命令之间的关系识别死代码,并去除识别出的死代码。可将这种编译方法称为“死代码去除”方案。 编译方法通过使用死代码去除方案从至少一个第一操作命令中识别死代码,并可不对识别出的死代码进行编译。因此,在产生的第二程序代码中可能不存在与死代码具有相同ID的第二操作命令。在这种情况下,由于不存在在操作S140中与死代码的第一操作结果相比较的目标对象,所以可不对死代码的第一操作结果进行验证。在操作S120的过程期间在编译操作中存在错误的情况下,可去除第一操作命令(不是死代码)。在这种情况下,由于可在所述至少一个第二操作命令的第二操作结果中找到编译操作中的错误,所以不用验证操作S140中的死代码的第一操作结果就可检测所述错误。 执行程序代码的处理器可通过使用单个管线结构或多个管线结构来处理操作命令。由于通过使用多个管线结构处理操作命令的处理器可并行处理多个操作命令,所以所述处理器可减少执行程序代码的时间。 在并行处理器并行处理多个操作命令中,不可以并行执行所有操作命令。单个操作命令可通过使用另一操作命令的输出值来执行操作。使用另一操作命令的输出值作为输入值的操作命令具有与其他操作命令相关的数据。由于在操作命令之间存在数据相关性,所以可能不能完全使得通过使用并行处理器执行程序代码的时间最小化。 为了使在并行处理器中执行程序代码的时间最小化,编译器可通过调整操作命令的顺序选择在操作命令之间不具有相关性的操作命令,并安排选择的操作命令被同时执行。这种操作可被称为“调度操作”。 可基于并行处理器的硬件配置来确定并行处理器同时执行的操作命令的数量。在并行处理器包括并行运行的多个功能单元的情况下,并行处理器可同时处理与所述多个功能单元的数量一样多的操作命令。 可考虑可在并行处理器中处理的操作命令的数量来执行编译器的调度操作。即使在操作命令之间不具有相关性的操作命令的数量较大,在并行处理器中可被同时执行的操作命令的数量也可能有限。 可将操作命令的操作结果存储在寄存器中。寄存器可以是相对快速的存储器,并可在后来的操作命令使用操作命令的操作结果之前临时存储操作结果。 可基于硬件配置来限制寄存器的数量。在处理器被嵌入到半导体中的情况下,由于寄存器在半导体中可占据相对大的区域,所以处理器可包括有限数量的寄存器。 在不限制寄存器数量的条件下,用户通常对程序代码编程。编译器可转换程序代码,从而程序代码可根据给定的寄存器的数量被执行。 如果在编译之前在程序代码中同时需要的寄存器的数量大于给定的寄存器的数量,则编译器可选择多出的寄存器的部分,并添加将选择的寄存器的内容存储在存储器中的操作命令。由于存储器中存储的选择的寄存器的内容可能在寄存器中没有被保持,所以编译器可通过如上所述添加操作命令来减少在程序代码中同时使用的寄存器的数量。该操作可被称为“寄存器分配”。寄存器分配操作可添加将存储的内容加载到寄存器的操作命令。在其他操作命令不使用寄存器的情况下,可通过添加的操作命令将存储器中存储的内容加载到寄存器,并可通过后来的命令使用所述内容。 通过寄存器分配操作所添加的添加的操作命令可被称为“溢出代码”。可另外存储关于单个溢出代码将其内容存储在存储器的特定地址的寄存器的信息。在执行程序代码的同时,可通过另外存储的信息将存储器中存储的内容加载到寄存器。可根据后进先出(LIFO)或先进后出(FILO)的顺序来存储另外存储的信息。为了便于描述,可将根据这些顺序存储的数据结构称为“堆栈结构”,并可将另外存储的数据称为“堆栈信息”。 在执行寄存器分配或调度操作的同时,编译器可增加程序代码中的操作命令的数量。在这种情况下,通过编译操作产生的第二程序代码的第二操作命令的数量可大于第一程序代码的第一操作命令的数量。 通过编译操作最新产生的第二操作命令可能不具有操作ID,或者可能具有最新分配的操作ID。 最新分配的操作ID可以是第一操作命令中不存在的操作ID。由于与经编译操作最新产生的第二操作命令相应的第一操作命令可能不存在,所以在操作S140,最新产生的第二操作命令的操作结果可能不被验证。 在操作S110,通过参照第二程序代码的堆栈信息来建立堆栈空间,并可通过使用建立的堆栈空间对第一程序代码进行仿真。在这种情况下,在操作S110可通过参照添加的溢出代码来建立堆栈空间的大小。 图3示出在编译之前的示例性程序代码。 参照图3,第一行310的操作命令具有操作ID op1。第一行310的操作命令将“0”存储在寄存器r1中。 第二行320的操作命令具有操作ID op2。第二行320的操作命令将“0”存储在寄存器r2中。 第三行330的操作命令具有操作ID op3。第三行330的操作命令将“2”存储在寄存器r4中。 第四行340的操作命令具有操作ID op4。第四行340的操作命令将寄存器r2和“1”之和存储在寄存器r1中。 第五行350的操作命令具有操作ID op5。第五行350的操作命令将寄存器r4和“3”之和存储在寄存器r3中。 第六行360的操作命令具有操作ID op6。第六行360的操作命令将“4”存储在寄存器r5中。 第七行370的操作命令具有操作ID op7。第七行370的操作命令将寄存器r3和寄存器r5之和存储在寄存器r5中。 第八行380的操作命令具有操作ID op8。第八行380的操作命令将寄存器r1和寄存器r5之和存储在寄存器r5中。 图4示出根据示例性实施例的图3的程序代码中使用的寄存器的活性。 参照图4,帧401指示第一行310,帧402指示第二行320,帧403指示第三行330。帧404指示第四行340,帧405指示第五行350,帧406指示第六行360。帧407指示第七行370,帧408指示第八行380。 在第一行310,寄存器r1存储“0”。然而,存储的值没有被其他操作命令使用。 在第四行340,寄存器r1存储值,并且存储的值被第八行380的操作命令使用。因此,在第四行340至第八行380的时间段,寄存器r1是活跃的,从帧404至帧408显示寄存器r1的活性410。 在第二行320,寄存器r2存储值,存储的值被第四行340的操作命令使用。因此,在从第二行320至第四行340的时间段,寄存器r2是活跃的,并从帧402至帧404显示寄存器r2的活性420。 在第五行350,寄存器r3存储值,存储的值被第七行370的操作命令使用。因此,在从第五行350至第七行370的时间段,寄存器r3是活跃的,并从帧405至帧407显示寄存器r3的活性430。 在第三行330,寄存器r4存储值,存储的值被第五行350的操作命令使用。因此,在从第三行330至第五行350的时间段,寄存器r4是活跃的,并从帧403至帧405显示寄存器r4的活性440。 在第六行360,寄存器r5存储值,存储的值被第八行380的操作命令使用。因此,在从第六行360至第八行380的时间段,寄存器r5是活跃的,并从帧406至帧408显示寄存器r5的活性450。 通过参照图4的活性的图示,可理解同时活跃的寄存器的数量。作为示例,寄存器r1、r2和r4可基于帧404活跃。由于在帧404之后不使用寄存器r2,所以编译器可在帧404之后用寄存器r1来代替寄存器r2。 通过从帧404至帧405的时间段,能理解,寄存器r1和r4是活跃的。因此,寄存器r1和r4不可相互替代。 如上所述,可限制处理器中包括的物理寄存器的数量。图3和图4中描述的寄存器是在编译之前程序代码的逻辑寄存器。在物理寄存器的数量小于同时需要的逻辑寄存器的数量的情况下,编译器可通过执行寄存器分配添加用于将寄存器的部分内容存储在存储器中的操作命令。在其他操作命令中使用的寄存器的数量减小的情况下,编译器可添加用于将存储器中存储的部分内容加载到寄存器的操作命令。编译器可通过使用图4的寄存器的活性的图示来执行寄存器分配。 图5示出根据示例性实施例的图4的寄存器之间的冲突。 参照图5,节点510指示寄存器r1,节点520指示寄存器r2,节点530指示寄存器r3,节点540指示寄存器r4,节点550指示寄存器r5。 节点之间的线指示与节点相应的寄存器之间的冲突。 在图4的帧404中,寄存器r2终止其功能,并且寄存器r1开始其功能。在帧404之后,由于寄存器r2的值不影响寄存器r1,所以能理解,寄存器r1和寄存器r2相互不冲突。在这种情况下,指示寄存器r1的节点510和指示寄存器r2的节点520没有相互连接。 相互不冲突的逻辑寄存器可被映射在单个物理寄存器上。在图3的程序代码中,即使在将逻辑寄存器r1和r2映射在单个物理寄存器的情况下,例如,在p1中,操作结果也没有变化。 在图4的寄存器的活性的图示中,由于在寄存器r1是活跃的同时,寄存器r3、r4和r5也是活跃的,所以寄存器r1与寄存器r3、r4和r5冲突。线501表示寄存器r1和寄存器r3相互冲突,线503表示寄存器r1和r5相互冲突,线504表示寄存器r1和r4相互冲突。 参照图4中的活性的图示,由于在寄存器r3是活跃的同时,寄存器r1和r5也是活跃的,所以寄存器r3与寄存器r1和r5冲突。线502表示寄存器r3和r5相互冲突。 参照图4中的活性的图示,由于在寄存器r2是活跃的同时,寄存器r4也是活跃的,所以寄存器r2与寄存器r4冲突。线505表示寄存器r2和r4相互冲突。 如果编译器将寄存器r2映射在物理寄存器p1,则可将与寄存器r2冲突的寄存器r4映射在物理寄存器p2。由于寄存器r1与寄存器r4冲突,所以可将寄存器r1映射在与寄存器p2不同的物理寄存器上。由于寄存器r1与寄存器r2不冲突,所以编译器可将寄存器r1映射在物理寄存器p1上。 由于寄存器r3与寄存器r1冲突,所以编译器可将寄存器r3映射在物理寄存器p2上。由于寄存器r5与寄存器r1和r3冲突,所以编译器可将寄存器r5映射在物理寄存器p1或物理寄存器p2上。寄存器r5可被映射在另外的存储器p3上。 因此,需要至少三个物理寄存器来执行图3的程序代码。如果可以只使用处理器的两个物理寄存器,则需要将溢出代码添加到图3的程序代码,以在处理器中执行图3的程序代码。 图6示出根据示例性实施例的图3的编译的程序代码。 参照图6,第一行610的操作命令具有操作ID op2。第一行610的操作命令将“0”存储在寄存器r2中。 第二行620的操作命令具有操作ID op3。第二行620的操作命令将“2”存储在寄存器r4中。 第三行630的操作命令具有操作ID op4。第三行630的操作命令将寄存器r2和“1”之和存储在寄存器r1中。 第四行640的操作命令具有操作ID op11。第四行640的操作命令是将寄存器r1的值存储在存储器[sp+4]中的操作命令,即溢出代码。 编译器可不向溢出代码分配操作ID。然而,由于编译器可用添加的溢出代码对程序代码再次编译,所以编译器可向溢出代码分配新的操作ID。以上“sp”指示堆栈指针,“sp+4”指示当前堆栈指针的后面的位置。根据一方面,示出了包括四个字节的单个字的示例,因此,堆栈指针的增量是4。依据实施例,可基于处理器和存储器的结构来确定堆栈指针的增加。 第五行650的操作命令具有操作ID op5。第五行650的操作命令将寄存器r4和“3”之和存储在寄存器r3中。 第六行660的操作命令具有操作ID op6。第六行660的操作命令将“4”存储在寄存器r5中。 第七行670的操作命令具有操作ID op7。第七行670的操作命令将寄存器r3和寄存器r5之和存储在寄存器r5中。 第八行680的操作命令具有操作ID op12。第八行680的操作命令是将存储器[sp+4]中存储的值加载到寄存器r1的操作命令,即溢出代码。 第九行690的操作命令具有操作ID op8。第九行690的操作命令将寄存器r1和寄存器r5之和存储在寄存器r5中。 如上所述,在图3的第一行310的操作命令中,寄存器r1中存储的值不被后来的操作命令使用。第一行310的操作命令是死代码,编译器可去除该死代码。 在编程代码中,在编译之后,如图6所示,应该理解,不存在与死代码相应的操作ID op1。 图7示出根据示例性实施例的图6的程序代码中使用的寄存器的活性。 参照图7,帧710指示图6的第一行610,帧720指示第二行620,帧730指示第三行630。帧740指示第四行640,帧750指示第五行650,帧760指示第六行660,帧770指示第七行670,帧780指示第八行680,帧790指示第九行690。 在第三行630,寄存器r1存储值,并且存储的值经第四行640的操作命令被存储在存储器中。在将寄存器r1中存储的值移动到存储器之后,寄存器r1被认为不是活跃的。 在从第三行630至第四行640的时间段,寄存器r1是活跃的,从帧730至帧740显示寄存器r1的第一活性701。 经第八行680的操作命令将从寄存器r1移动到存储器的值从存储器加载到寄存器r1。第九行690的操作命令使用加载的值。因此,在图6的第八行680至第九行690的时间段,寄存器r1是活跃的,并从帧780至帧790显示寄存器r1的第二活性702。 在第一行,寄存器r2存储值,并且存储的值被第三行630的操作命令使用。因此,在第一行610至第三行630的时间段,寄存器r2是活跃的,并从帧710至帧730显示寄存器r2的活性703。 在第五行650,寄存器r3存储值,并且存储的值被第七行670的操作命令使用。因此,在第五行650至第七行670的时间段,寄存器r3是活跃的,并从帧750至帧770显示寄存器r3的活性704。 在第二行620,寄存器r4存储值,并且存储的值被第五行650的操作命令使用。因此,在第二行620至第五行650的时间段,寄存器r4是活跃的,并从帧720至帧750显示寄存器r4的活性705。 在第六行660,寄存器r5存储值,并且存储的值被第九行690的操作命令使用。因此,在第六行660至第九行690的时间段,寄存器r5是活跃的,并从帧760至帧790显示寄存器r5的活性706。 将图7的活性的图示与图4的活性的图示进行比较,应该理解,将图4的寄存器r1的活性410分成比活性410短的图7的两个活性701和702。由于在帧740至帧780的时间段,寄存器r1不是活跃的,所以在帧740至帧780的时间段期间,不需要将物理寄存器映射在寄存器r1上。 在图7的活性的图示中,应该理解,可将寄存器r1、r2和r3映射在单个物理寄存器上,可将寄存器r4和r5映射在另一物理寄存器上。通过将图3的程序代码编译为图6的程序代码,编译的程序代码只需要两个物理寄存器。 可通过使用图8的冲突的图示来执行将逻辑寄存器映射在物理寄存器上的操作。 图8示出根据示例性实施例的图7的寄存器之间的冲突。 参照图8,节点810指示寄存器r1,节点820指示寄存器r2,节点830指示寄存器r3。节点840指示寄存器r4,节点850指示寄存器r5。 节点之间的线指示与节点相应的寄存器之间的冲突。 在图7的活性的图示中,由于在寄存器r1是活跃的从帧730至帧740的时间段寄存器r4是活跃的,所以寄存器r1和寄存器r4相互冲突。线803表示寄存器r1和寄存器r4相互冲突。 由于在寄存器r1是活跃的从帧780至帧790的时间段寄存器r5是活跃的,所以寄存器r1和寄存器r5相互冲突。线801表示寄存器r1和寄存器r5相互冲突。 由于在寄存器r2是活跃的从帧710至帧730的时间段,寄存器r4是活跃的,所以寄存器r2和寄存器r4相互冲突。线804表示寄存器r2和寄存器r4相互冲突。 由于在寄存器r3是活跃的从帧750至帧770的时间段寄存器r5是活跃的,所以寄存器r3和寄存器r5相互冲突。线802表示寄存器r3和寄存器r5相互冲突。 参照图7和图8,编译器可顺序地从帧710映射逻辑寄存器。 在帧710,编译器可将逻辑寄存器r2映射在物理寄存器p1上。编译器可将与逻辑寄存器r2冲突的逻辑寄存器r4映射在物理寄存器p2上。 编译器可将与逻辑寄存器r4冲突的逻辑寄存器r1映射在物理寄存器p1上。编译器可将与逻辑寄存器r1冲突的逻辑寄存器r5映射在物理寄存器p2上。 编译器可将与逻辑寄存器r5冲突的逻辑寄存器r3映射在物理寄存器p1上。 从而,编译器可通过使用图8的冲突的图示,将逻辑寄存器r1、r2和r3映射在物理寄存器p1,并可将寄存器r4和r5映射在物理寄存器p2上。 如上所述,可在具有两个物理寄存器的处理器中无差错地执行图6的程序代码。逻辑寄存器和物理寄存器之间的映射操作可被称为“寄存器分配”。 图9示出根据示例性实施例的在图6的程序代码被寄存器分配之后的程序代码。参照图9,第一行910的操作命令具有操作ID op2。第一行910的操作命令将“0”存储在寄存器p1中。 图9的程序代码是在将图6的程序代码的逻辑寄存器映射到物理寄存器之后的程序代码。由于在先前的编译操作期间已经分配了溢出代码,所以图9的程序代码的每个操作命令可具有与图6的程序代码的每个操作命令相同的操作ID。 第二行920的操作命令具有操作ID op3。第二行920的操作命令将“2”存储在寄存器p2中。 第三行930的操作命令具有操作ID op4。第三行930的操作命令将寄存器p1和“1”之和存储在寄存器p1中。 第四行940的操作命令具有操作ID op11。第四行940的操作命令是将寄存器p1的值存储在存储器[sp+4]中的操作命令。 第五行950的操作命令具有操作ID op5。第五行950的操作命令将寄存器p2和“3”之和存储在寄存器p1中。 第六行960的操作命令具有操作ID op6。第六行960的操作命令将“4”存储在寄存器p2中。 第七行970的操作命令具有操作ID op7。第七行970的操作命令将寄存器p1和寄存器p2之和存储在寄存器p2中。 第八行980的操作命令具有操作ID op12。第八行980的操作命令是将存储器[sp+4]中存储的值加载到寄存器p1的操作命令。 第九行990的操作命令具有操作ID op8。第九行990的操作命令将寄存器p1和寄存器p2之和存储在寄存器p2中。第九行990的操作命令向寄存器p2提供最终结果值。由于逻辑寄存器r5对应于物理寄存器p2,所以图9的程序代码可向逻辑寄存器r5提供最终结果值。 参照图1、图3和图5,操作S140将具有相同操作ID的操作命令的操作结果进行比较。作为示例,具有操作ID op5的图3的操作命令将“5”(即,存储“2”的寄存器r4和“3”之和)存储在寄存器r3中。具有操作ID op5的图9的操作命令将存储“2”的寄存器p2和“3”之和“5”存储在寄存器p1中。 上述两个操作结果同为“5”。根据一方面,可通过跟踪由编译器变换的程序代码的每个操作命令来检测变换操作期间的错误。根据一方面,可通过选择合适的程序代码来验证编译器的变换操作,并且一旦检测到错误,就向用户报告所述错误。根据一方面,由于具有在变换操作的过程中发生的错误的操作命令被识别,所以可容易地改正错误。根据一方面,编译器可在具有相同操作ID的操作命令具有相同输入和输出值的条件下执行编译操作。在以上条件下,尽管操作命令的操作数不同,但是具有相同操作ID的操作命令的操作结果具有相同的输入和输出值。 图10示出根据示例性实施例的编译器和该编译器的调试方法。 参照图10,编译器对容易在编译器中处理的中间表示(IR)进行编译,以将IR转换成容易在处理器中处理的编程语言。 编译器根据代码选择方案执行未调度的IR 1001,从而包括用于产生代码选择的IR 1003的选择模块1002。 编译器可包括调度模块1004,所述调度模块1004通过调度代码选择的IR 1003来产生调度的IR1005。 编译器可包括通过对调度的IR 1005进行寄存器分配来产生寄存器分配的IR 1007的寄存器分配模块1006。 编译器的调试方法可通过使用仿真器1008产生未调度的IR 1001的操作结果(1)1012。编译器的调试方法可通过使用仿真器1009产生代码选择的IR1003的操作结果(2)1014。 编译器的调试方法可通过使用验证模块1013将操作结果(1)1012与操作结果(2)1014进行比较。在操作结果(1)1012与操作结果(2)1014不同的情况下,编译器的调试方法认为在编译器中存在错误,并可向用户报告操作结果不同的操作ID。 编译器的调试方法可通过使用仿真器1010产生调度的IR1005的操作结果(3)1016。编译器的调试方法可通过使用验证模块1015将操作结果(2)1014与操作结果(3)1016进行比较。在操作结果(2)1014与操作结果(3)1016不同的情况下,编译器的调试方法认为在编译器中存在错误,并可向用户报告操作结果不同的操作ID。 编译器的调试方法可通过使用仿真器1011产生使用的寄存器分配的IR1007的操作结果(4)1018。编译器的调试方法可通过使用验证模块1017将操作结果(3)1016与操作结果(4)1018进行比较。在操作结果(3)1016与操作结果(4)1018不同的情况下,编译器的调试方法认为,在编译器中存在错误,并可向用户报告操作结果不同的操作ID。 图11示出根据示例性实施例的处理器1100。 如图11所示,处理器1100包括:代码转换器1110、第一仿真器1120和第二仿真器1130。 处理器1100可包括多个功能单元,并根据将并行执行的操作命令来使用所述多个功能单元。 代码转换器1110可对第一程序代码进行编译,以产生第二程序代码。第一程序代码可包括至少一个第一操作命令,第二程序代码可包括至少一个第二操作命令。 第一仿真器1120对第一操作代码进行仿真,以产生第一操作结果。第二仿真器1130对第二程序代码进行仿真,以产生第二操作结果。处理器1100可以是能够并行处理操作命令的可重构处理器,第一程序代码可以是描述的适合于在处理器1100中执行的程序代码。 第一仿真器1120可通过使用所述多个功能单元来并行处理所述至少一个第一操作命令。第二仿真器1130可通过使用所述多个功能单元来并行处理所述至少一个第二操作命令。 代码转换器1110可向所述至少一个第一操作命令中的每一个分配操作ID。 处理器1100可将第一操作命令的第一操作结果和具有与第一操作命令的操作标识符相同的操作标识符的第二操作命令的第二操作结果进行比较。处理器1100可通过检测至少一个第一操作命令和至少一个第二操作命令的每个操作结果来验证第二程序代码是否有效。 处理器1100可通过验证第二程序代码的有效性来验证代码转换器1110的编译操作的有效性。 代码转换器1110可对第一程序代码进行寄存器分配,以使当执行第一程序代码时同时活跃的寄存器的数量不超过硬件支持的寄存器的数量。 代码转换器1110可将通过对第一程序代码进行寄存器分配产生的第二程序代码的堆栈信息发送到第一仿真器1120。第一仿真器1120可通过参照堆栈信息来对第一程序代码仿真。 以上描述的包括编译器的编译和/或调试方法的方法可被记录、存储或固定在一个或多个计算机可读介质中,所述计算机可读介质包括将被计算机实现的程序指令,以使得处理器运行或执行所述程序指令。所述介质还可单独包括程序指令、数据文件、数据结构等,或者可包括程序指令、数据文件、数据结构等的组合。计算机可读介质的示例包括:磁性介质,例如硬盘、软盘和磁带;光学介质,例如CD ROM盘和DVD;磁光介质,例如,光盘;和被具体配置以存储和执行程序指令的硬件装置,例如,只读存储器(ROM)、随机存取存储器(RAM)、闪存等。程序指令的示例包括:机器代码,例如由编译器产生的代码;和文件,包含可通过使用解释器由计算机执行的高级代码。所述硬件装置可被配置为用作一个或多个软件模块,以执行上述操作和方法。 以上已经描述了几个示例性实施例。不过,应该理解,可进行各种修改。例如,如果以不同的顺序执行描述的技术,和/或如果所描述的系统中的部件、体系结构、装置或电路被以不同的方式组合和/或被其他部件或等同物代替或补充,则可实现适当的结果。因此,其他实现在权利要求的范围内。
《编译方法和使用该编译方法的处理器.pdf》由会员分享,可在线阅读,更多相关《编译方法和使用该编译方法的处理器.pdf(32页珍藏版)》请在专利查询网上搜索。
提供了一种编译方法和使用该编译方法的处理器。所述方法包括:对包括至少一个第一操作命令的第一程序代码进行仿真,以产生第一操作结果;对第一程序代码进行编译,以产生包括至少一个第二操作命令的第二程序代码;对第二程序代码进行仿真,以产生第二操作结果;将第一操作结果与第二操作结果进行比较,以验证第二程序代码是否有效。 。
copyright@ 2017-2020 zhuanlichaxun.net网站版权所有经营许可证编号:粤ICP备2021068784号-1