CN103942083B - 一种面向可变参函数的编译实现方法 - Google Patents

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

Info

Publication number
CN103942083B
CN103942083B CN201410173673.7A CN201410173673A CN103942083B CN 103942083 B CN103942083 B CN 103942083B CN 201410173673 A CN201410173673 A CN 201410173673A CN 103942083 B CN103942083 B CN 103942083B
Authority
CN
China
Prior art keywords
parameter
stack
variable
variable element
storage
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Active
Application number
CN201410173673.7A
Other languages
English (en)
Other versions
CN103942083A (zh
Inventor
王霁
孙海燕
阳柳
张雪萌
陈书明
郭阳
刘衡竹
陈跃跃
龚国辉
李�灿
陈伟业
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
National University of Defense Technology
Original Assignee
National University of Defense Technology
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by National University of Defense Technology filed Critical National University of Defense Technology
Priority to CN201410173673.7A priority Critical patent/CN103942083B/zh
Publication of CN103942083A publication Critical patent/CN103942083A/zh
Application granted granted Critical
Publication of CN103942083B publication Critical patent/CN103942083B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Landscapes

  • Devices For Executing Special Programs (AREA)

Abstract

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

Description

一种面向可变参函数的编译实现方法
技术领域
本发明涉及高级语言编译器领域,尤其涉及一种面向可变参函数的编译实现方法。
背景技术
可变参函数是一类特殊的函数,其函数声明中除了包含至少一个固定参数以外,还包含尚未确定的其它参数,而在函数中是通过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结构体中通过栈传递的参数的存放地址加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。
作为本发明的进一步改进,所述步骤(2)的具体步骤为:
(2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);
(2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;
(2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放。
与现有技术相比,本发明的优点在于:
1)本发明将可变参函数中的固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参都通过栈来传递,既有效的利用了参数寄存器、避免了硬件资源的浪费,又能分别对固定参数和可变参数进行不同的处理,执行效率高、硬件资源利用率高且灵活性强。
2)本发明在参数的查找中,每执行完一次va_arg函数之后当前va_list结构体指针指向的是当前参数的位置,也就是下一个参数所要储存位置的前一个存储单元位置,不论下一个参数是什么类型,都可以方便的找到其对应的存储位置,而不需要根据参数类型进行调整,免去了繁琐的判断、计算参数大小等复杂的步骤,使得编译处理简单便捷、执行效率高。
附图说明
图1是传统的普通函数参数传递过程的处理方法流程示意图。
图2是本实施例一种面向可变参函数的编译实现方法流程示意图。
图3是本实施例中参数传递方法流程示意图。
具体实施方式
以下结合说明书附图和具体优选的实施例对本发明作进一步描述,但并不因此而限制本发明的保护范围。
如图2所示,本实施例一种面向可变参函数的编译实现方法,步骤为:
(1)第一个可变参数位置确定:获取函数原型中固定参数的个数,并根据固定参数的个数确定第一个可变参数的存放位置,其中当固定参数的个数不超过参数寄存器的数量时,第一个可变参数的存放位置为指定的栈传递参数的起始位置,否则为最后一个固定参数存放位置的后一个存储单元;
(2)参数的传递和存储:读取函数中的参数,根据固定参数的个数判断当前参数的类型,若为固定参数,优先通过参数寄存器传递和存储,没有可用的参数寄存器时通过栈进行传递和存储;若为可变参数,通过栈进行传递并从第一个可变参数存放位置开始依次进行存储;
(3)参数的查找:从第一个可变参数的存放位置开始遍历参数,根据参数的存放位置获取参数,并根据下一个参数的大小更新得到下一个参数的存放位置,直至获取得到所有的可变参数。
本实施例在可变参函数的传递和存储中,将固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参数都通过栈来传递,既有效的利用了参数寄存器,同时能够避免硬件资源的浪费;在参数的查找过程中,根据当前参数的存放位置及下一个参数的大小更新得到下一个参数的存放位置。
本实施例中,步骤(1)的具体步骤如下:
步骤1.1:定义args结构体和varargs结构体两个结构体类型,分别用来存储普通参数信息和可变参数信息;对varargs结构体进行初始化并获取函数原型中参数的个数。
本实施例中,args结构体和varargs结构体为:
struct args {
int nregs;
int count;
int incoming_args_size;
};
typedef struct
{
int named_arg_num;
int reg_save_num;
int reg_save_size;
int stack_save_size;
} varargs;
由于可变参函数的参数和普通参数也存在着一定的共性,在处理时需要用到对一般参数的处理,因此需要存储普通参数的信息。本实施例中,args结构体存储普通参数信息,由成员变量nregs存储当前参数所需占用的参数寄存器数量,若当前参数的长度没有超过一个字,则所需占用参数寄存器的数量为一个;若超过一个字,则所需占用参数寄存器的数量为一个以上;由成员变量count存储当前参数为第几个被传递的参数;由成员变量incoming_args_size存储当前参数的大小。
本实施例中,varargs结构体用来存储可变参数信息,其中成员变量named_arg_num存储函数原型中固定参数的个数,根据固定参数的个数可以确定后续参数传递的处理;成员变量reg_save_num 和 reg_save_size 存储已经通过参数寄存器传递的参数的个数、大小;成员变量stack_save_size则是存储超过参数寄存器数量的固定参数所需占用的空间大小,即当固定参数个数超过参数寄存器的数量时,多出的固定参数通过栈传递时所需占用的空间大小。
本实施例中,定义结构体后对结构体varargs进行初始化,并获取函数原型中固定参数的个数n,根据函数原型中固定参数的个数确定后续处理,其中对结构体varargs进行初始化为:
varargs vararg=
{ 0, 0, 0, 0};
根据上述表达式可知,将varargs结构体中的变量named_arg_num、reg_save_num、reg_save_size及stack_save_size初始化为0。
步骤1.2:定义va_list结构体指针,指针包含两个域:一个是当前参数寄存器的编号gpr,另一个是通过栈传递的参数的存放地址overflow_arg_area。
本实施例中,va_list结构体包括成员变量参数寄存器的编号gpr、通过栈传递的参数的存放地址overflow_arg_area。固定参数是与参数寄存器一一对应的进行存储,每传递一个固定参数,当前参数寄存器的编号gpr就相应的增加,直到全部的参数寄存器都被使用。通过栈传递的参数的存放地址overflow_arg_area则存储通过栈传递时可变参数所存放的地址信息,在参数查找时,通过该地址查找到相应的可变参数。
步骤1.3:定义va_start 函数来对va_list结构体进行初始化,通过执行va_start函数获取第一个可变参数的存放位置;由得到的第一个可变参数的存放位置对va_list结构体进行初始化,使va_list结构体中通过栈传递的参数的存放地址overflow_arg_area初始化为第一个可变参数存放位置前一个存储单元的地址,并将地址值传递给va_arg函数。
本实施例中,由于固定参数、可变参数在传递存储时采用不同的方式进行处理,因此对于第一个变参数的存放位置存在以下两种情况:
第一种情况:可变参函数的声明中,固定参数的个数n没有超过参数寄存器的数目N时,则第一个可变参的存放位置就是编译器所指定的栈传递参数的起始位置,而编译器中栈传递参数的起始位置都是固定的,通常是由栈底指针加减一个固定大小的offset得到;
第二种情况:可变参函数的声明中的固定参数的个数n超过N个时,第一个可变参数的存放位置则位于最后一个固定参数存放位置后面的存储单元。
本实施例中,执行va_start 函数得到第一个可变参数的存放位置之后,将该存放位置的前一个存储单元的地址值赋给va_list结构体中的成员变量overflow_arg_area。这样无论可变参数是从栈传递参数的起始位置开始存储,还是存储在栈中固定参数所在位置后面的连续空间,第一个可变参数的存放位置都保存在了va_list结构体中。
本实施例中,当编译器进行编译时,根据函数声明中固定参数的个数对可变参数与固定参数进行不同的处理,步骤(2)的具体步骤为:
(2.1)参数类型判断:读取函数中参数,根据固定参数个数判断当前参数是否为可变参数,若为是,转入执行步骤(2.2);若为否,转入执行步骤(2.3);
(2.2)固定参数的传递:判断当前已传递的固定参数的数目是否大于参数寄存器数量,若为否,当前参数使用参数寄存器来进行传递,若为是,当前参数通过栈来进行传递;
(2.3)可变参数的传递:当没有使用栈传递固定参数时,可变参数从指定的栈传递参数的起始位置开始存放;当使用栈传递了固定参数时,可变参数从最后一个固定参数存放位置后的连续空间依次存放。
本实施例中,读取一个参数后,首先判断这个参数是固定参数还是可变参数,判断的方法为:由于可变参函数至少有一个固定参数,则由函数的声明即可以得到固定参数个数n,而编译器会对每一个读取的参数进行计数,如果当前参数的计数小于等于n,则说明该参数为固定参数,当计数大于固定参数个数n之后的参数均为可变参数。
本实施例中,假设编译器有N个用来传递参数的参数寄存器,对于不超过N个固定参数的一般函数,可以都用参数寄存器来进行传递固定参数,若固定参数超过N个参数,则超过的固定参数部分通过在栈中进行传递。可变参数都通过栈来进行传递,于是可变参数的存储存在两种情况:
第一种情况:可变参函数的声明中,固定参数没有超过N个时,则可变参函数从编译器所指定的栈传递参数的起始位置开始依次进行存放;
第二种情况:声明中的固定参数超过N个时,超出N个的那几个固定参数也通过栈来传递,可变参数从最后一个固定参数的存放位置之后开始依次进行存放。
如图3所示,本实施例中参数传递方法流程,根据可变参函数原型中参数个数确定固定参数、可变参数的参数传递方式,所有的可变参数全部都通过栈来传递,而根据固定参数个数n确定可变参数所存放的位置。如果为固定参数,则按照一般参数的传递原则在有可用的参数寄存器的条件下,使用参数寄存器{R1, R2, … RN}来进行传参,第一个固定参数传递时将存储到参数寄存器R1中,然后参数寄存器编号gpr加1,第二个固定参数存储到参数寄存器R2中,以此类推;当没有可用的参数寄存器时,即固定参数的个数n大于参数寄存器的数目N时,多出来的固定参数则通过栈来进行传递。
当为可变参数时,若没有使用栈传递固定参数,即固定参数的个数n小于等于参数寄存器的数目N,此时参数寄存器仍有剩余或正好使用完,固定参数并不占用栈空间来传递,因此可变参数从编译器所指定的栈传递参数的起始位置ARG1开始存放。栈传递参数的起始位置ARG1为栈底加上一个固定大小的offset,第一个需要通过栈来传递的参数存放在该起始位置,后续的参数相应的依次逐个的存放进起始位置之后的连续栈空间ARG2、ARG3……中。若使用栈传递了固定参数,即固定参数的个数n大于参数寄存器的数量N,固定参数无法全部通过参数寄存器传递,多出来的固定参数就会通过栈来传递,在这种情况下,第N+1个固定参数存储在栈传递参数的起始位置ARG1,第N+2个直到第n个固定参数依次进行存放至连续栈空间ARG2、ARG3……中。此时需要先计算第n个固定参数所存放的地址,然后将第一个可变参存放在第n个固定参数所在位置后面的连续空间中,后续的可变参数再依次向后进行存放。
本实施例将可变参函数中的将固定参数和可变参数进行分开处理,固定参数按照一般方法处理,优先通过参数寄存器来传参,而将所有的可变参都通过栈来传递。既有效的利用了参数寄存器,避免了硬件资源的浪费,又能分别对固定参数和可变参数进行不同的处理,执行效率高、硬件资源利用率稿、灵活性强。
本实施例中,步骤(3)的具体实施方法为:通过多次执行va_arg函数来进行遍历参数,同时根据参数类型的特点在正确的位置找到相应的参数。每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址overflow_arg_area得到上一个参数存储的内存地址,根据上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取当前参数,并更新va_list结构体中通过栈传递的参数的存放地址overflow_arg_area为计算得出的当前参数存储的内存地址,其中当获取第一个可变参数时,通过栈传递的参数的存放地址overflow_arg_area,即上一个参数存储的内存地址,为第一个可变参数存放位置的前一个存储单元的地址。
由于经过va_start 函数的初始化,va_list结构体中的overflow_arg_area指针已经指向了第一个可变参数存放位置的前一个存储单元位置,通过执行va_arg函数来进行遍历参数,就可以在正确的位置找到相应的参数。执行va_arg函数时,通过获取va_list结构体中通过栈传递的参数的存放地址overflow_arg_area找到参数所在位置,在每执行完一次va_arg函数后,va_list结构体中通过栈传递的参数的存放地址overflow_arg_area都会更新,将当前参数存储的内存地址值赋给va_list结构体,当前参数存储的内存地址也即为下一个参数存放位置的前一个存储单元的地址。这样通过迭代就可以依次获取每一个参数的地址,直到遍历所有的参数。
步骤(3)的关键问题在于所查找的参数的类型和数据对齐问题,如果一个参数类型的长度、超过一个字时,则该参数之后的参数位置会相应的后移,因此需要在给va_list结构体赋新值的时候要加上正确的位移;而如果当前参数类型的长度小于一个字,则要根据寻址方式来进行相应的对齐处理,以使正确读取到参数值。
本实施例中,计算出当前参数所存储的内存地址的具体实现方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址(即上一个参数存储的内存地址)加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。以下一个参数为单字类型为例,由va_list结构体存储的内存地址值加一个字的大小得到下一个参数要存储的位置;以下一个参数为双字类型为例,则需要加2个字的大小来得到下一个参数要存储的位置。
本实施例在执行完一次va_arg函数之后,当前va_list结构体指针指向的是当前参数存储的位置,也就是下一个参数所要储存的位置的前一个存储单元,在获得下一个参数的类型和大小之后,可以很方便的通过相加得到下一个参数的地址。传统的处理方法中,在执行完一次va_arg之后指向当前参数位置的后面那个位置,即下一个参数要存储的位置,若下一个参数超过一个字或者不足一个字时,可能会因为对齐方式以及内存存储的方式(大端或者小端模式)的不同需要进行进一步的调整,使得多了一步计算过程。因此采用本实施例进行可变参函数的编译,编译处理更加简单便捷、执行效率更高。
以上仅是本发明的优选实施方式,本发明的保护范围并不仅局限于上述实施例,凡属于本发明思路下的技术方案均属于本发明的保护范围。应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理前提下的若干改进和润饰,应视为本发明的保护范围。

Claims (3)

1.一种面向可变参函数的编译实现方法,其特征在于,步骤为:
(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函数。
2.根据权利要求1所述的面向可变参函数的编译实现方法,其特征在于,所述步骤(3)的具体实施方法为:多次执行va_arg函数,遍历并获取可变参数;每次执行va_arg函数时,由va_list结构体中通过栈传递的参数的存放地址得到上一个参数存储的内存地址,并根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址,获取参数后更新va_list结构体中通过栈传递的参数的存放地址为计算得出的当前参数存储的内存地址。
3.根据权利要求2所述的面向可变参函数的编译实现方法,其特征在于,所述根据所述上一个参数存储的内存地址、当前参数的大小计算出当前参数存储的内存地址的具体实施方法为:判断当前参数的参数类型的长度是否超过一个字,若为是,将va_list结构体中通过栈传递的参数的存放地址加上当前参数所需占用内存空间大小得到当前参数存储的内存地址;若为否,根据寻址方式进行对齐处理后得到当前参数存储的内存地址。
CN201410173673.7A 2014-04-28 2014-04-28 一种面向可变参函数的编译实现方法 Active CN103942083B (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN201410173673.7A CN103942083B (zh) 2014-04-28 2014-04-28 一种面向可变参函数的编译实现方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN201410173673.7A CN103942083B (zh) 2014-04-28 2014-04-28 一种面向可变参函数的编译实现方法

Publications (2)

Publication Number Publication Date
CN103942083A CN103942083A (zh) 2014-07-23
CN103942083B true CN103942083B (zh) 2017-10-17

Family

ID=51189759

Family Applications (1)

Application Number Title Priority Date Filing Date
CN201410173673.7A Active CN103942083B (zh) 2014-04-28 2014-04-28 一种面向可变参函数的编译实现方法

Country Status (1)

Country Link
CN (1) CN103942083B (zh)

Families Citing this family (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104391733B (zh) * 2014-12-10 2017-11-24 华中科技大学 一种依据依赖关系动态编译软件包的方法
CN104615583B (zh) * 2015-01-27 2017-11-28 上海联影医疗科技有限公司 基于gpu平台实现数据处理的方法和装置
CN106874305B (zh) * 2015-12-14 2020-08-21 北京国双科技有限公司 一种信息传递的方法及装置
CN112052004A (zh) * 2019-06-05 2020-12-08 深圳市汇顶科技股份有限公司 函数的参数优化方法、编译器、芯片及电子设备
CN112527263B (zh) * 2019-09-19 2022-10-04 无锡江南计算技术研究所 基于国产异构平台的自适应可变参数优化方法
CN112882695B (zh) * 2021-03-02 2023-11-28 百果园技术(新加坡)有限公司 传参方法、装置、计算机设备及存储介质

Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5481708A (en) * 1992-06-05 1996-01-02 Borland International, Inc. System and methods for optimizing object-oriented compilations
US7356812B2 (en) * 2003-09-30 2008-04-08 Intel Corporation Passing parameters by implicit reference
CN102109975A (zh) * 2009-12-24 2011-06-29 华为技术有限公司 确定函数调用关系的方法、装置及系统
CN102831005A (zh) * 2012-07-13 2012-12-19 天津国芯科技有限公司 针对C*core处理器寄存器分配的编译方法及编译器

Patent Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5481708A (en) * 1992-06-05 1996-01-02 Borland International, Inc. System and methods for optimizing object-oriented compilations
US7356812B2 (en) * 2003-09-30 2008-04-08 Intel Corporation Passing parameters by implicit reference
CN102109975A (zh) * 2009-12-24 2011-06-29 华为技术有限公司 确定函数调用关系的方法、装置及系统
CN102831005A (zh) * 2012-07-13 2012-12-19 天津国芯科技有限公司 针对C*core处理器寄存器分配的编译方法及编译器

Non-Patent Citations (4)

* Cited by examiner, † Cited by third party
Title
C/C++语言可变参数函数的参数传递机制剖析;顾晖;《电脑与信息技术》;20040630(第3期);第37-38,41页 *
C语言的调用惯例与变参函数设计;苑向兵等;《计算机系统应用》;19980131(第1期);第25-27页 *
SAM8系列S3C825型单片机及其软件设计;贺兴华等;《国外电子元器件》;20050831(第8期);第47-51页 *
基于ARM的汇编语言与C语言混合编程的方法研究;杜钦生等;《长春大学学报》;20111031;第21卷(第10期);第19-23页 *

Also Published As

Publication number Publication date
CN103942083A (zh) 2014-07-23

Similar Documents

Publication Publication Date Title
CN103942083B (zh) 一种面向可变参函数的编译实现方法
US20200204501A1 (en) Data-plane stateful processing units in packet processing pipelines
US10819633B2 (en) Data-plane stateful processing units in packet processing pipelines
CN109215728B (zh) 用于分布式存储器危险检测和错误恢复的存储器电路和方法
EP3726389A1 (en) Apparatuses, methods, and systems for memory interface circuit allocation in a configurable spatial accelerator
US10891240B2 (en) Apparatus, methods, and systems for low latency communication in a configurable spatial accelerator
DE102018126150A1 (de) Einrichtung, verfahren und systeme für multicast in einem konfigurierbaren räumlichen beschleuniger
CN109597646A (zh) 具有可配置空间加速器的处理器、方法和系统
KR100237090B1 (ko) 제어 집중 시스템
DE60010907T2 (de) Sram-steuerungvorrichtung für parallele prozessorarchitektur mit adressen- und befehlswarteschlange und arbiter
DE102018006735A1 (de) Prozessoren und Verfahren für konfigurierbares Clock-Gating in einem räumlichen Array
CN110088737A (zh) 将并发程序转换为可部署在基于fpga的云基础设施上的硬件的综合路径
CN101799760A (zh) 生成任意目标架构的并行单指令多数据代码的系统和方法
Guck et al. Analysis of timed and long-run objectives for Markov automata
CN108292267A (zh) 总线-装置-功能地址空间的推测性枚举
CN110430444A (zh) 一种视频流处理方法及系统
CN107003944B (zh) 跨分布式存储器的指针追踪
Klauske et al. Improved layout for data flow diagrams with port constraints
CN103327118B (zh) 一种针对云计算中web应用的智能虚拟机集群缩放方法及系统
Dworzański et al. On compositionality of boundedness and liveness for nested Petri nets
JPH09114676A (ja) マイクロコンピュータ用プログラム変換方法及びそのプログラムを用いたマイクロコンピュータ
Staskauskas Formal derivation of concurrent programs: An example from industry
Chan et al. A multiplier adjustment approach for the set partitioning problem
Cabarle et al. Notes on spiking neural P systems and finite automata
Danalis et al. Automatic MPI application transformation with ASPhALT

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
GR01 Patent grant
GR01 Patent grant