88typedef struct
99{
1010 size_t stack_size ;
11+ size_t lr_offset ;
12+ int save_lr ;
1113} cj_builder_frame ;
1214
1315typedef struct
@@ -39,6 +41,10 @@ typedef struct
3941
4042static inline void cj_builder_fn_prologue (cj_ctx * ctx , size_t requested_stack_bytes ,
4143 cj_builder_frame * frame );
44+ static inline void cj_builder_fn_prologue_with_link_save (cj_ctx * ctx , size_t requested_stack_bytes ,
45+ cj_builder_frame * frame );
46+ static inline void cj_builder_fn_prologue_ex (cj_ctx * ctx , size_t requested_stack_bytes ,
47+ cj_builder_frame * frame , int save_lr );
4248static inline void cj_builder_fn_epilogue (cj_ctx * ctx , const cj_builder_frame * frame );
4349static inline void cj_builder_return (cj_ctx * ctx , const cj_builder_frame * frame );
4450
@@ -100,44 +106,26 @@ static inline size_t align_stack_size(size_t size)
100106static inline void cj_builder_fn_prologue (cj_ctx * ctx , size_t requested_stack_bytes ,
101107 cj_builder_frame * frame )
102108{
103- if (!ctx )
104- return ;
105-
106- size_t aligned = align_stack_size (requested_stack_bytes );
107- if (frame )
108- frame -> stack_size = aligned ;
109-
110- #if defined(__x86_64__ ) || defined(_M_X64 )
111- cj_operand rbp = cj_make_register ("rbp" );
112- cj_operand rsp = cj_make_register ("rsp" );
113-
114- cj_push (ctx , rbp );
115- cj_mov (ctx , rbp , rsp );
109+ cj_builder_fn_prologue_ex (ctx , requested_stack_bytes , frame , 0 );
110+ }
116111
117- if (aligned )
118- {
119- cj_operand amount = cj_make_constant ((uint64_t )aligned );
120- cj_sub (ctx , rsp , amount );
121- }
122- #elif defined(__aarch64__ ) || defined(_M_ARM64 )
123- cj_operand sp = cj_make_register ("sp" );
124- if (aligned )
125- {
126- cj_operand amount = cj_make_constant ((uint64_t )aligned );
127- cj_sub (ctx , sp , amount );
128- }
129- #endif
112+ static inline void cj_builder_fn_prologue_with_link_save (cj_ctx * ctx , size_t requested_stack_bytes ,
113+ cj_builder_frame * frame )
114+ {
115+ cj_builder_fn_prologue_ex (ctx , requested_stack_bytes , frame , 1 );
130116}
131117
132118static inline void cj_builder_fn_epilogue (cj_ctx * ctx , const cj_builder_frame * frame )
133119{
134120 if (!ctx )
135121 return ;
136122 size_t aligned = frame ? frame -> stack_size : 0 ;
123+ int save_lr = (frame && frame -> save_lr );
137124
138125#if defined(__x86_64__ ) || defined(_M_X64 )
139126 cj_operand rbp = cj_make_register ("rbp" );
140127 cj_operand rsp = cj_make_register ("rsp" );
128+ (void )save_lr ;
141129
142130 if (aligned )
143131 {
@@ -148,12 +136,23 @@ static inline void cj_builder_fn_epilogue(cj_ctx *ctx, const cj_builder_frame *f
148136 cj_pop (ctx , rbp );
149137#elif defined(__aarch64__ ) || defined(_M_ARM64 )
150138 cj_operand sp = cj_make_register ("sp" );
139+ size_t total = aligned + (save_lr ? 16 : 0 );
151140
152- if (aligned )
141+ if (save_lr )
153142 {
154- cj_operand amount = cj_make_constant ((uint64_t )aligned );
143+ size_t lr_offset = frame ? frame -> lr_offset : aligned ;
144+ cj_operand lr = cj_make_register ("x30" );
145+ cj_operand slot = cj_make_memory ("sp" , NULL , 1 , (int32_t )lr_offset );
146+ cj_ldr (ctx , lr , slot );
147+ }
148+
149+ if (total )
150+ {
151+ cj_operand amount = cj_make_constant ((uint64_t )total );
155152 cj_add (ctx , sp , amount );
156153 }
154+ #else
155+ (void )save_lr ;
157156#endif
158157}
159158
@@ -671,3 +670,53 @@ cj_builder_call(cj_ctx *ctx, cj_builder_scratch *scratch, cj_label target,
671670
672671 return cj_builder_return_reg ();
673672}
673+
674+ static inline void cj_builder_fn_prologue_ex (cj_ctx * ctx , size_t requested_stack_bytes ,
675+ cj_builder_frame * frame , int save_lr )
676+ {
677+ if (!ctx )
678+ return ;
679+ assert (!save_lr || frame );
680+
681+ size_t aligned = align_stack_size (requested_stack_bytes );
682+ size_t lr_offset = aligned ;
683+ if (frame )
684+ {
685+ frame -> stack_size = aligned ;
686+ frame -> save_lr = save_lr ? 1 : 0 ;
687+ frame -> lr_offset = save_lr ? lr_offset : 0 ;
688+ }
689+
690+ #if defined(__x86_64__ ) || defined(_M_X64 )
691+ (void )save_lr ;
692+ cj_operand rbp = cj_make_register ("rbp" );
693+ cj_operand rsp = cj_make_register ("rsp" );
694+
695+ cj_push (ctx , rbp );
696+ cj_mov (ctx , rbp , rsp );
697+
698+ if (aligned )
699+ {
700+ cj_operand amount = cj_make_constant ((uint64_t )aligned );
701+ cj_sub (ctx , rsp , amount );
702+ }
703+ #elif defined(__aarch64__ ) || defined(_M_ARM64 )
704+ size_t total = aligned + (save_lr ? 16 : 0 );
705+ cj_operand sp = cj_make_register ("sp" );
706+
707+ if (total )
708+ {
709+ cj_operand amount = cj_make_constant ((uint64_t )total );
710+ cj_sub (ctx , sp , amount );
711+ }
712+
713+ if (save_lr )
714+ {
715+ cj_operand lr = cj_make_register ("x30" );
716+ cj_operand slot = cj_make_memory ("sp" , NULL , 1 , (int32_t )lr_offset );
717+ cj_str (ctx , lr , slot );
718+ }
719+ #else
720+ (void )save_lr ;
721+ #endif
722+ }
0 commit comments