一种面向可变参函数的编译实现方法技术

技术编号:16390440 阅读:36 留言:0更新日期:2017-10-17 13:36
本发明专利技术公开一种面向可变参函数的编译实现方法,步骤为:1)获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数存放位置;2)读取函数中参数,判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递;3)从第一个可变参数开始遍历参数,根据参数的存放位置获取参数并根据参数大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。本发明专利技术具有实现方法简单、操作便捷、硬件资源利用率高、执行效率高、灵活性强的优点。

【技术实现步骤摘要】
一种面向可变参函数的编译实现方法
本专利技术涉及高级语言编译器领域,尤其涉及一种面向可变参函数的编译实现方法。
技术介绍
可变参函数是一类特殊的函数,其函数声明中除了包含至少一个固定参数以外,还包含尚未确定的其它参数,而在函数中是通过va_list,va_start,va_arg等关键字来实现参数的迭代和查找。可变参数在格式化输入输出中具有较多的应用,编译器在编译这类函数时,由于不知道具体的参数个数,对可变参数的处理方式和普通函数有很大的区别,编译器需要考虑到可能出现的各种情况,如参数的位置,传参的方式等。要正确的实现可变参函数的编译有以下两个要点:(1)父函数按照正确的规则将参数存放在正确的位置;(2)子函数能够按照一定的规则去正确的位置找到所需要的参数;这两个要点都和参数传递方式以及栈帧存储方式密切相关,而对于不同的体结构来说,参数传递和存储的方式都不一样,因此编译器需要针对特定的体系结构做特定的处理,才能保证正确编译可变参函数。对于可变参函数程序的编译实现,其关键是定义和处理va_list、va_start和va_arg这几个关键字,通常情况下每个上述关键字都需要定义一个相应的函数来进行,这三个关键字所实现的功能分别为:va_list关键字:va_list关键字在可变参中所起的作用是定义一个可变参的指针,存储可变参信息,如参数寄存器编号、参数类型以及当前参数存储位置等。va_list可以是一个包含多个成员变量的结构体,也可以仅仅是一个指针变量。va_start关键字:va_start关键字所起的作用是对va_list进行初始化,将指针指向第一个可变参所存储的位置(也有可能是第一个可变参之前的那个位置),使得va_arg能够准确定位,将后面的参数逐一的找到。第一个可变参所存储的位置是与栈帧布局息息相关,通常会结合普通参数的处理过程,共同决定其存放位置,而不同的可变参编译方法对于这一步的处理方法会有所不同。va_arg关键字:va_arg关键字是遍历所有参数,在正确的位置找到相应的可变参数。va_arg在一个程序中可以多次执行,每执行一次,都会获取当前的参数的存储地址,执行完以后,指向当前参数地址的指针会向后面移动,指向下一个参数的位置,以此类推,完成所有可变参数的查找。目前对于可变参函数的编译方法中,参数传递方法主要有两种:方法1:所有的参数不论是否为可变参,都通过栈来传递,只要计算出是第几个参数,即可获取该参数的存储地址,即可变参数和普通参数处理方法相同。方法2:在还有可用的参数寄存器的情况下,可变参函数使用参数寄存器来传递,参数寄存器使用完以后,再通过栈来进行传递,每次变量指针都指向下一个参数的存储位置。如图1所示,传统的普通函数参数传递处理方法,其中N为参数寄存器的数目,该数目与体系结构相关,可根据需要定义其大小。进行参数传递时,首先逐个读取参数并计数,如果当前参数的数目小于N,说明还有可用的参数寄存器,当前参数则通过参数寄存器来传递并且将已使用的参数寄存器数目增加1;当前参数数目正好等于N时,说明当前参数寄存器已经使用完,当前参数是最后一个可以通过寄存器来传递的参数;当前参数数目大于N时,参数则全部通过栈来传递。编译器会根据体系结构特点和栈帧布局等来指定一个栈传递参数的存放起始位置,通常情况下是由栈指针加上一个固定大小的偏移量offset来得到该起始位置。确定了起始位置后,就能够确定通过栈传递的第一个参数的位置,后续的参数依次进行传递存储,直到完成整个传参的过程。对于方法1,由于没有使用寄存器传参,不能充分的利用寄存器,且全部通过栈来传递加大了内存开销,尤其是将非可变参函数的参数和可变参函数的固定参数也都通过栈来传递,造成很大的空间浪费、降低执行效率,且所有参数采用同样的处理方法进行处理,其灵活性也较差。对于方法2,虽然能够充分利用参数寄存器,但是由于可变参函数的可变参无论是数目还是类型都是不固定的,处理过程复杂而繁琐。在计算可以通过参数寄存器来传递的可变参数个数以及通过栈传递剩余参数的个数时,需要考虑许多复杂的情况,如参数有可能是char、int或double类型,甚至为结构体类型,有时参数需要占用一个以上的参数寄存器,这样通过参数寄存器传递的参数数目就会相应的减少。另一方面,每次执行完一次va_arg,变量指针都指向下一个参数的存储位置,通常是在当前参数的位置加一个字的大小得到下一个参数的存储位置,但假如下一个参数所占的大小并非一个字,而是小于或者大于一个字,那么该变量指针还需要进行相应的调整。此类处理方法会将很多冗余繁琐的情况考虑在内,且有可能需要进行一定的调整,大大降低便捷性,不利于实际应用。
技术实现思路
本专利技术要解决的技术问题就在于:针对现有技术存在的技术问题,本专利技术提供一种实现方法简单、操作便捷、硬件资源利用率高、执行效率高、灵活性强的面向可变参函数的编译实现方法。为解决上述技术问题,本专利技术提出的技术方案为:一种面向可变参函数的编译实现方法,步骤为:(1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;(2)参数的传递:读取函数中的参数,根据固定参数个数判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;(3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。作为本专利技术的进一步改进,所述步骤(1)的具体步骤为:(1.1)获取函数原型中固定参数的个数,并定义一个用于存储参数寄存器编号、通过栈传递的参数的存放地址的va_list结构体;(1.2)定义并执行va_start函数,获取第一个可变参数的存放位置,当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;(1.3)将va_list结构体中通过栈传递的参数的存放地址初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。作为本专利技术的进一步改进,所述步骤(3)的具体实施方法为:多次执行va_arg函数,遍历并获取可变参数;每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址得到上一个参数存储的内存地址,并根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取参数后更新va_list结构体中通过栈传递的参数的存放地址为计算得出的当前参数存储的内存地址。作为本专利技术的进一步改进,所述根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址的具体实施方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻本文档来自技高网
...
一种面向可变参函数的编译实现方法

【技术保护点】
一种面向可变参函数的编译实现方法,其特征在于,步骤为:(1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;(2)参数的传递:读取函数中的参数,根据固定参数个数判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;所述步骤(2)的具体步骤为:(2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);(2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;(2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放;(3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数;所述步骤(1)的具体步骤为:(1.1)获取函数原型中固定参数的个数,并定义一个用于存储参数寄存器编号、通过栈传递的参数的存放地址的va_list结构体;(1.2)定义并执行va_start函数,获取第一个可变参数的存放位置,当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;(1.3)将va_list结构体中通过栈传递的参数的存放地址初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。...

【技术特征摘要】
1.一种面向可变参函数的编译实现方法,其特征在于,步骤为:(1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置后的存储单元;(2)参数的传递:读取函数中的参数,根据固定参数个数判断当前参数是否为可变参数,若为否,优先通过参数寄存器传递,没有可用的参数寄存器时通过栈进行传递;若为是,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;所述步骤(2)的具体步骤为:(2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);(2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;(2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放;(3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数;所述步骤(1)的具体步骤为:(1.1)获取函数原型中固定参数...

【专利技术属性】
技术研发人员:王霁孙海燕阳柳张雪萌陈书明郭阳刘衡竹陈跃跃龚国辉李灿陈伟业
申请(专利权)人:中国人民解放军国防科学技术大学
类型:发明
国别省市:湖南,43

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1