A method of dynamically allocating caller-saved register save space
By dynamically allocating the storage space of the caller's storage register, the problems of stack space waste and high complexity in the existing technology are solved, achieving more efficient stack space management and a simplified implementation process, which is suitable for various backend architectures.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- 成都融见软件科技有限公司
- Filing Date
- 2026-04-24
- Publication Date
- 2026-07-03
AI Technical Summary
In the existing technology, the stack space allocation for caller-saved registers is wasteful, complex, and prone to errors, including the problem that the stack space increases with the number of calls and the unified reserved space is not fully utilized.
By dynamically allocating the storage space of the caller's storage register, the storage space is temporarily allocated according to the actual needs of the current call point and released immediately after the call ends, thus avoiding the waste of a uniformly reserved area and the complex information transmission process.
It reduces the overall stack usage of functions, avoids the waste of stack space as the number of calls increases, simplifies the implementation process, reduces the probability of errors, and is applicable to a variety of backend architectures.
Smart Images

Figure CN122086469B_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of compilers, and in particular to a method for dynamically allocating caller-save register storage space. Background Technology
[0002] Existing technologies for allocating stack space for caller-saved registers present the following problems: 1. Stack space continuously increases with the number of calls. To maintain the uniqueness of stack offsets, existing compilers allocate a new location on the stack for each caller-saved register save. This causes multiple call points within a function to continuously request space from the bottom of the stack, resulting in a linear increase in stack usage and significant stack space waste. 2. A unified caller-saved storage area leads to space waste. Existing compilers typically reserve a unified caller-saved storage area at the function entry stage based on the maximum demand from all call points. However, the actual number of registers that different call points need to save varies considerably. A unified reservation requires calculation based on the maximum demand, which still results in underutilization of space for most call points. 3. The implementation is complex and prone to errors. Existing technologies require recording the set of caller-saved registers for each call point during the register allocation stage, then deriving the size of the unified storage area based on this information during the rewrite stage, and generating save and restore instructions based on a fixed offset during the rewrite stage. The entire process involves multi-stage information transfer, offset calculation, and storage order processing, which is highly complex and prone to errors. Summary of the Invention
[0003] The purpose of this invention is to provide a method for dynamically allocating caller-save register storage space to solve the problems of stack space waste, high complexity, and susceptibility to errors mentioned above.
[0004] According to the present invention, a method for dynamically allocating caller-saved register storage space is provided. The method is applied during the register allocation phase and includes the following steps:
[0005] S100, obtain the set of caller save registers that need to be saved at the current call point.
[0006] S200: Based on the set of caller save registers that need to be saved, obtain the save space size N required for the current call point.
[0007] S300 allocates a contiguous save space of size N for this call by adjusting the stack pointer before generating the save instruction.
[0008] S400 writes the value of the caller's save register that needs to be saved at the current call point into a contiguous save space of size N allocated for this call.
[0009] S500 executes function call instructions.
[0010] S600 restores the values of each caller-saved register written in the contiguous storage space of size N allocated for this call to the corresponding caller-saved register after the function call returns.
[0011] S700, restore the stack pointer to release the contiguous storage space of size N allocated for this call.
[0012] Compared with the prior art, the present invention has at least the following beneficial effects:
[0013] This invention allocates storage space only temporarily based on the actual number of registers needed at the current call point, eliminating the need to reserve a unified storage area for all call points and reducing overall stack usage. Furthermore, the storage space allocated for a single call is released immediately after the call ends, ensuring the stack pointer remains consistent before and after the call, preventing the stack space from accumulating with each call and avoiding the problem of stack space growing cumulatively. In addition, this invention eliminates the need to pass information such as the caller-saved register set for each call point to the rewrite stage and to plan a unified storage area, as well as the need to handle fixed offsets during the rewrite stage. This localizes the storage logic, reduces implementation complexity, and decreases the risk of errors.
[0014] Furthermore, this invention maintains the correctness of access to variables on the stack by adjusting the offset of instructions that use stack pointer addressing during temporary changes in the stack pointer, and does not rely on a specific register allocation algorithm, making it suitable for various backend architectures. Attached Figure Description
[0015] To more clearly illustrate the technical solutions in the embodiments of the present invention, the accompanying drawings used in the description of the embodiments will be briefly introduced below. Obviously, the accompanying drawings described below are only some embodiments of the present invention. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.
[0016] Figure 1 A flowchart illustrating a method for dynamically allocating caller-save register storage space according to an embodiment of the present invention;
[0017] Figure 2 This is a first schematic diagram of stack space allocation provided in an embodiment of the present invention;
[0018] Figure 3This is a second schematic diagram of stack space allocation provided for an embodiment of the present invention. Detailed Implementation
[0019] The technical solutions of the embodiments of the present invention will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of the present invention, and not all embodiments. Based on the embodiments of the present invention, all other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of the present invention.
[0020] According to this embodiment, a method for dynamically allocating caller-saved register storage space is provided. This method is applied during the register allocation phase and includes the following steps: Figure 1 As shown:
[0021] S100, obtain the set of caller save registers that need to be saved at the current call point.
[0022] It should be understood that the register allocation phase is an important phase in the compiler backend. The main task of this phase is to map an infinite number of virtual registers to the finite number of physical registers on the target machine. When there are not enough physical registers, the register allocator will decide to spill some variables onto the stack (called spill).
[0023] It should be understood that a call point refers to the location of a function call within a program. For example, in the compiler's intermediate representation (IR), a call point is represented by a `call` instruction or an `invoke` instruction (used for exception handling). Each call point is an independent location, and the set of caller-saved registers that need to be saved may differ. In this embodiment, the current call point refers to the location of the function call currently being processed.
[0024] It should be understood that caller-saved registers are registers that the calling convention specifies the caller is responsible for saving. Before a function call, if a caller-saved register contains data that will still be needed after the call, the caller must save the value of that register onto the stack; after the call returns, it is restored from the stack. The callee can use these registers freely without being responsible for saving them.
[0025] S200: Based on the set of caller save registers that need to be saved, obtain the save space size N required for the current call point.
[0026] In one specific implementation, S200 includes: obtaining the required storage space size N for the current call point based on the number of registers in the caller-saved register set to be saved, the width of the registers, and the stack alignment requirements of the target platform. Here, the register width refers to the number of bits or bytes of data that a register can store, and the register width determines the number of stack space bytes required to save a register value; the register width may differ in different architectures, for example, 8 bytes or 16 bytes. The stack alignment requirements of the target platform refer to the requirement that the stack pointer must remain a multiple of a certain value during specific operations. For example, some platforms require the stack pointer to be aligned to a 16-byte boundary before a function call. For example, if the target platform requires the stack pointer to be aligned to 16 bytes, the register width is 8 bytes, and the current call point needs to save 3 caller-saved registers (3 × 8 = 24 bytes), then considering the alignment requirements, the required storage space size for the 3 caller-saved registers is 32 bytes, that is, N is 32 bytes.
[0027] S300 allocates a contiguous save space of size N for this call by adjusting the stack pointer before generating the save instruction.
[0028] In this embodiment, the save instruction refers to the instruction that writes the value of the caller-saved register into a contiguous save space of size N allocated for this call.
[0029] In one specific implementation, the stack grows towards lower addresses, and a contiguous storage space of size N is allocated for this call by moving the stack pointer down by N (i.e., subtracting N from the stack pointer).
[0030] S400 writes the value of the caller's save register that needs to be saved at the current call point into a contiguous save space of size N allocated for this call.
[0031] In this embodiment, if the caller-saved register set that the current calling point needs to save includes multiple registers, these registers can be written sequentially into a contiguous save space of size N allocated for this call. For example, if the target platform requires the stack pointer to be aligned to 16 bytes and the register width to be 8 bytes, and the current calling point needs to save 3 caller-saved registers, then N is 32 bytes, and the extra 8 bytes of space can be left empty.
[0032] S500 executes function call instructions.
[0033] In this embodiment, executing a function call instruction means that after saving the value of the caller-saved register, when the program reaches the function call instruction, the instruction will be executed to realize the function call.
[0034] S600 restores the values of each caller-saved register written in the contiguous storage space of size N allocated for this call to the corresponding caller-saved register after the function call returns.
[0035] In this embodiment, the called function has already finished executing when the function call returns. As a specific implementation, during restoration, the values of each register are read from a contiguous storage space of size N allocated for this call, following the same order as when it was saved previously, and then written back to the corresponding physical registers.
[0036] S700, restore the stack pointer to release the contiguous storage space of size N allocated for this call.
[0037] In this embodiment, the stack pointer is restored by generating an instruction that is symmetrical to the adjustment operation in S300. For example, if the adjustment operation in S300 is to decrement the stack pointer by N, then the stack pointer needs to be incremented by N when restoring the stack pointer.
[0038] In this embodiment, the method further includes: processing the next call point after S700. The process of processing the next call point is similar to the process of S100-S700; the next call point is simply used as the current call point in S100-S700, and will not be described in detail here.
[0039] In this embodiment, the allocated storage space is only temporarily requested based on the actual number of registers needed at the current call point, without reserving a unified storage area for all call points, thus reducing the overall stack usage of the function. Furthermore, the storage space allocated for a single call is released immediately after the call ends, ensuring the stack pointer remains consistent before and after the call, preventing the stack space from growing with the number of calls and avoiding the problem of cumulative stack space growth. In addition, this embodiment eliminates the need to pass information such as the caller-saved register set for each call point to the rewrite stage and to plan a unified storage area, as well as the need to handle fixed offsets during the rewrite stage, localizing the storage logic, reducing implementation complexity, and minimizing errors.
[0040] In one specific implementation, the method further includes: if there is an instruction located after the stack pointer is adjusted and before the stack pointer is restored, and the instruction uses the stack pointer as its base address, then the stack offset of the instruction is updated to ensure correct access to the instruction.
[0041] It should be understood that, between the time the stack pointer is adjusted in S300 and the time the stack pointer is restored in S700, instructions generated during this interval may use the stack pointer as a base address to access data on the stack. This data may include local variables, overflow slots, etc. Because the stack pointer is temporarily moved during this interval (e.g., moved down by N), while the absolute address of the data on the stack remains unchanged, the original offset relative to the original stack pointer needs to be adjusted accordingly to correctly access the original data.
[0042] As a specific implementation, updating the stack offset of the instruction includes: if adjusting the stack pointer in S300 is to subtract N from the stack pointer, then when the data corresponding to the instruction is written to the stack, the stack offset corresponding to the position written to the stack is updated to be the original stack offset minus N.
[0043] In one specific implementation, the method further includes: if there is an instruction located after the stack pointer is adjusted and before the stack pointer is restored, then the space occupied by the instruction is released first, and then the contiguous storage space of size N allocated for this call is released.
[0044] In one specific implementation, the stack space occupied by the data corresponding to the instruction is released by incrementing the stack pointer by M, and the contiguous storage space of size N allocated for this call is released by incrementing the stack pointer by N; M is the stack space occupied by the instruction.
[0045] This embodiment maintains the correctness of access to variables on the stack by adjusting the offset of instructions that use stack pointer addressing during temporary changes in the stack pointer. It does not rely on a specific register allocation algorithm and can be used in a variety of backend architectures.
[0046] For example, taking the x86_64 platform as an example, suppose there is the following function call in a certain function: printf("%lu,%lu,%lu,%lu,%lu,%lu",1,2,3,4,5,6).
[0047] According to the calling convention of the x86_64 platform, when the number of function parameters exceeds the capacity of the parameter registers (i.e., 6), the parameters must be pushed onto the stack. In the example above, the contents of the first 6 parameter registers are shown in Table 1, and parameter 6 must be placed on the stack, specifically at address sp+0 in the callee. The contents of the 6 parameter registers remain unchanged in this example and are omitted below.
[0048] Table 1
[0049]
[0050] For ease of explanation, the following explanation uses stack frames, such as... Figure 2As shown, the callee corresponds to the next stack frame in the diagram, while the caller's stack frame corresponds to the portion between the previous and next stack frames. The stack grows downwards. Stack space allocation is achieved by moving the special register, the stack pointer (SP). According to the calling convention, SP needs to be 16-byte aligned. Dynamically allocated stack space stores function parameter 6, which the callee can access via SP'+0.
[0051] Assume the compiler register allocation process reaches this point and discovers that the caller-saved register (denoted as r10) is active at the call site, and its contents need to be saved onto the stack. Considering stack alignment, r10 requires 16 bytes of storage space. Before saving the value of r10 and placing the function parameters, first update SP to SP'' and write the value of r10 from the position of SP''; then update SP to SP' and write 6 from the position of SP', as shown below. Figure 3 As shown.
[0052] After executing the function call and returning, the saved value of r10 needs to be written back to r10. Since SP now corresponds to the position of SP', the content to be written back to r10 should be SP+16. Then, the stack space is released.
[0053] The corresponding instruction sequence in the above process is shown in Table 2.
[0054] Table 2
[0055]
[0056] In Table 2, the instruction sequence is executed from top to bottom. The second column of the table is the explanation of the instruction corresponding to the first column of the table, which will not be repeated here.
[0057] While specific embodiments of the invention have been described in detail by way of example, those skilled in the art should understand that the examples are for illustrative purposes only and not intended to limit the scope of the invention. It should also be understood that various modifications can be made to the embodiments without departing from the scope and spirit of the invention. The scope of the invention is defined by the appended claims.
Claims
1. A method for dynamically allocating caller-save register storage space, characterized in that, The method is applied during the register allocation phase and includes the following steps: S100, obtain the set of caller save registers that need to be saved at the current call point; S200, based on the set of caller save registers that need to be saved, obtain the save space size N required for the current call point; S300 allocates a contiguous save space of size N for this call by adjusting the stack pointer before generating the save instruction; S400: Write the value of the caller's save register that needs to be saved at the current call point into a contiguous save space of size N allocated for this call; S500 executes function call instructions; S600, after the function call returns, restores the values of each caller save register written in the contiguous save space of size N allocated for this call to the corresponding caller save register; S700, restore the stack pointer to release the contiguous storage space of size N allocated for this call.
2. The method for dynamically allocating caller-save register storage space according to claim 1, characterized in that, The method further includes: if there is an instruction located after the stack pointer is adjusted and before the stack pointer is restored, and the instruction uses the stack pointer as its base address, then the stack offset of the instruction is updated to ensure correct access to the instruction.
3. The method for dynamically allocating caller-save register storage space according to claim 2, characterized in that, The update of the stack offset of the instruction includes: if the stack pointer is adjusted in S300 to subtract N from the stack pointer, then when the data corresponding to the instruction is written to the stack, the stack offset corresponding to the position written to the stack is updated to be the original stack offset minus N.
4. The method for dynamically allocating caller-save register storage space according to claim 3, characterized in that, The method further includes: if there is an instruction located after the stack pointer is adjusted and before the stack pointer is restored, then the stack space occupied by the instruction is released first, and then the contiguous storage space of size N allocated for this call is released.
5. The method for dynamically allocating caller-save register storage space according to claim 4, characterized in that, The stack space occupied by the data corresponding to the instruction is released by incrementing the stack pointer by M, and the contiguous storage space of size N allocated for this call is released by incrementing the stack pointer by N; M is the stack space occupied by the instruction.
6. The method for dynamically allocating caller-save register storage space according to claim 1, characterized in that, S200 includes: obtaining the required storage space size N for the current call point based on the number of registers in the caller's save register set to be saved, the width of the registers, and the stack alignment requirements of the target platform.
7. The method for dynamically allocating caller-save register storage space according to claim 1, characterized in that, The method further includes processing the next call point after S700.