From 03559bb8cc47ad7a1f8ae5a35d128f06e1b736b9 Mon Sep 17 00:00:00 2001 From: pcpa Date: Fri, 14 Dec 2012 15:21:39 -0200 Subject: [PATCH] Make it clear stdarg like abstraction is not supported. * include/lightning.h, include/lightning/jit_private.h, lib/jit_arm.c, lib/jit_mips.c, lib/jit_ppc.c, lib/jit_x86.c, lib/lightning.c: Make jit_ellipsis implementation not backend specific. It is not intended to handle va_list like objects at runtime, as jit_arg* and jit_getarg* return constant values resolved at parse time, so, effectively it is not possible to create printf like jit functions, as there is no va_start, va_arg, va_end, etc, abstraction. This limitation should be kept for the sake of making new ports easier. --- ChangeLog | 13 +++++++++++++ include/lightning.h | 7 ------- include/lightning/jit_private.h | 7 ++++++- lib/jit_arm.c | 21 +++++++++------------ lib/jit_mips.c | 10 +++------- lib/jit_ppc.c | 13 +++++-------- lib/jit_x86.c | 15 ++++++--------- lib/lightning.c | 26 +++++++++++++++++++++++++- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7149bf6c..b0802dd3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-12-14 Paulo Andrade + + * include/lightning.h, include/lightning/jit_private.h, + lib/jit_arm.c, lib/jit_mips.c, lib/jit_ppc.c, lib/jit_x86.c, + lib/lightning.c: Make jit_ellipsis implementation not + backend specific. It is not intended to handle va_list + like objects at runtime, as jit_arg* and jit_getarg* + return constant values resolved at parse time, so, effectively + it is not possible to create printf like jit functions, as + there is no va_start, va_arg, va_end, etc, abstraction. This + limitation should be kept for the sake of making new ports + easier. + 2012-12-14 Paulo Andrade * include/lightning.h, lib/lightning.c: Add two extra wrapper diff --git a/include/lightning.h b/include/lightning.h index 366969542..35fcfa758 100644 --- a/include/lightning.h +++ b/include/lightning.h @@ -95,13 +95,6 @@ typedef jit_int32_t jit_fpr_t; #define jit_class(reg) ((reg) & 0xffff0000) #define jit_regno(reg) ((reg) & 0x00007fff) -#define jit_call_default 0 -/* assume only varags functions called are printf like, that is, - * without a declared float/double argument */ -/* FIXME currently no way to create a varargs (or non varargs) jit function - * if calling sequence changes for float/double arguments */ -#define jit_call_varargs 1 - typedef struct jit_node jit_node_t; typedef struct jit_state jit_state_t; diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h index 6107ffa78..959af0f86 100644 --- a/include/lightning/jit_private.h +++ b/include/lightning/jit_private.h @@ -61,6 +61,9 @@ * returned by a "user" call * to jit_get_reg() */ +#define jit_call_default 0 +#define jit_call_varargs 1 + #define jit_kind_register 1 #define jit_kind_code 2 #define jit_kind_word 3 @@ -194,12 +197,13 @@ struct jit_function { jit_int32_t size; jit_int32_t aoff; jit_int32_t alen; + jit_int32_t call; } self; struct { jit_int32_t argi; jit_int32_t argf; jit_int32_t size; - jit_int32_t kind; + jit_int32_t call; } call; jit_node_t *prolog; jit_node_t *epilog; @@ -220,6 +224,7 @@ struct jit_state { jit_node_t *tail; jit_uint32_t emit : 1; /* emit state entered */ jit_uint32_t again : 1; /* start over emiting function */ + jit_uint32_t prepare : 1; /* inside prepare/finish* block */ jit_int32_t reglen; /* number of registers */ jit_regset_t regarg; /* cannot allocate */ jit_regset_t regsav; /* automatic spill only once */ diff --git a/lib/jit_arm.c b/lib/jit_arm.c index e4af92ef0..4ecdb0d3c 100644 --- a/lib/jit_arm.c +++ b/lib/jit_arm.c @@ -228,6 +228,7 @@ _jit_prolog(jit_state_t *_jit) _jit->function->self.aoff = -64; else _jit->function->self.aoff = 0; + _jit->function->self.call = jit_call_default; _jit->function->regoff = calloc(_jit->reglen, sizeof(jit_int32_t)); _jit->function->prolog = jit_new_node_no_link(jit_code_prolog); @@ -243,12 +244,6 @@ _jit_prolog(jit_state_t *_jit) jit_regset_new(_jit->function->regset); } -void -_jit_ellipsis(jit_state_t *_jit) -{ - _jit->function->call.kind = jit_call_varargs; -} - jit_int32_t _jit_allocai(jit_state_t *_jit, jit_int32_t length) { @@ -355,7 +350,7 @@ jit_int32_t _jit_arg_f(jit_state_t *_jit) { jit_int32_t offset; - if (jit_cpu.abi) { + if (jit_cpu.abi && !(_jit->function->self.call & jit_call_varargs)) { if (_jit->function->self.argf < 16) offset = _jit->function->self.argf++; else { @@ -378,7 +373,7 @@ jit_int32_t _jit_arg_d(jit_state_t *_jit) { jit_int32_t offset; - if (jit_cpu.abi) { + if (jit_cpu.abi && !(_jit->function->self.call & jit_call_varargs)) { if (_jit->function->self.argf < 15) { if (_jit->function->self.argf & 1) ++_jit->function->self.argf; @@ -525,7 +520,7 @@ void _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u) { assert(_jit->function); - if (jit_cpu.abi && !(_jit->function->call.kind & jit_call_varargs)) { + if (jit_cpu.abi && !(_jit->function->call.call & jit_call_varargs)) { if (_jit->function->call.argf < 16) { jit_movr_f(JIT_FA0 - _jit->function->call.argf, u); ++_jit->function->call.argf; @@ -549,7 +544,7 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u) jit_int32_t regno; assert(_jit->function); - if (jit_cpu.abi && !(_jit->function->call.kind & jit_call_varargs)) { + if (jit_cpu.abi && !(_jit->function->call.call & jit_call_varargs)) { if (_jit->function->call.argf < 16) { jit_movi_f(JIT_FA0 - _jit->function->call.argf, u); ++_jit->function->call.argf; @@ -574,7 +569,7 @@ void _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) { assert(_jit->function); - if (jit_cpu.abi && !(_jit->function->call.kind & jit_call_varargs)) { + if (jit_cpu.abi && !(_jit->function->call.call & jit_call_varargs)) { if (_jit->function->call.argf < 15) { if (_jit->function->call.argf & 1) ++_jit->function->call.argf; @@ -604,7 +599,7 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) jit_int32_t regno; assert(_jit->function); - if (jit_cpu.abi && !(_jit->function->call.kind & jit_call_varargs)) { + if (jit_cpu.abi && !(_jit->function->call.call & jit_call_varargs)) { if (_jit->function->call.argf < 15) { if (_jit->function->call.argf & 1) ++_jit->function->call.argf; @@ -664,6 +659,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0) node->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; } jit_node_t * @@ -679,6 +675,7 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0) node->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; return (node); } diff --git a/lib/jit_mips.c b/lib/jit_mips.c index bfca2062c..d3cca00cb 100644 --- a/lib/jit_mips.c +++ b/lib/jit_mips.c @@ -135,6 +135,7 @@ _jit_prolog(jit_state_t *_jit) _jit->function->self.size = stack_framesize; _jit->function->self.argi = _jit->function->self.argf = _jit->function->self.aoff = _jit->function->self.alen = 0; + _jit->function->self.call = jit_call_default; _jit->function->regoff = calloc(_jit->reglen, sizeof(jit_int32_t)); _jit->function->prolog = jit_new_node_no_link(jit_code_prolog); @@ -150,12 +151,6 @@ _jit_prolog(jit_state_t *_jit) jit_regset_new(_jit->function->regset); } -void -_jit_ellipsis(jit_state_t *_jit) -{ - _jit->function->call.kind = jit_call_varargs; -} - jit_int32_t _jit_allocai(jit_state_t *_jit, jit_int32_t length) { @@ -612,6 +607,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0) call->w.w = _jit->function->self.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; } jit_node_t * @@ -629,7 +625,7 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0) call->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; - + _jit->prepare = 0; return (node); } diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index 6e5da810e..df6007ebd 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -141,6 +141,7 @@ _jit_prolog(jit_state_t *_jit) _jit->function->self.aoff = _jit->function->self.alen = 0; /* float conversion */ _jit->function->self.aoff = -8; + _jit->function->self.call = jit_call_default; _jit->function->regoff = calloc(_jit->reglen, sizeof(jit_int32_t)); _jit->function->prolog = jit_new_node_no_link(jit_code_prolog); @@ -156,12 +157,6 @@ _jit_prolog(jit_state_t *_jit) jit_regset_new(_jit->function->regset); } -void -_jit_ellipsis(jit_state_t *_jit) -{ - _jit->function->call.kind = jit_call_varargs; -} - jit_int32_t _jit_allocai(jit_state_t *_jit, jit_int32_t length) { @@ -425,7 +420,7 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) if (_jit->function->call.argf < 8) { jit_movr_d(JIT_FA0 - _jit->function->call.argf, u); ++_jit->function->call.argf; - if (!(_jit->function->call.kind & jit_call_varargs)) + if (!(_jit->function->call.call & jit_call_varargs)) return; } if (_jit->function->call.argi < 8) { @@ -452,7 +447,7 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) if (_jit->function->call.argf < 8) { jit_movi_d(JIT_FA0 - _jit->function->call.argf, u); ++_jit->function->call.argf; - if (!(_jit->function->call.kind & jit_call_varargs)) + if (!(_jit->function->call.call & jit_call_varargs)) return; } regno = jit_get_reg(jit_class_fpr); @@ -505,6 +500,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0) call->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; } jit_node_t * @@ -519,6 +515,7 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0) node->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; return (node); } diff --git a/lib/jit_x86.c b/lib/jit_x86.c index 918af4160..8386a851e 100644 --- a/lib/jit_x86.c +++ b/lib/jit_x86.c @@ -305,6 +305,7 @@ _jit_prolog(jit_state_t *_jit) _jit->function->self.aoff = _jit->function->self.alen = 0; /* sse/x87 conversion */ _jit->function->self.aoff = -8; + _jit->function->self.call = jit_call_default; _jit->function->regoff = calloc(_jit->reglen, sizeof(jit_int32_t)); _jit->function->prolog = jit_new_node_no_link(jit_code_prolog); @@ -320,12 +321,6 @@ _jit_prolog(jit_state_t *_jit) jit_regset_new(_jit->function->regset); } -void -_jit_ellipsis(jit_state_t *_jit) -{ - _jit->function->call.kind = jit_call_varargs; -} - jit_int32_t _jit_allocai(jit_state_t *_jit, jit_int32_t length) { @@ -732,7 +727,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0) if (_jit->function->self.alen < _jit->function->call.size) _jit->function->self.alen = _jit->function->call.size; #if __WORDSIZE == 64 - if (_jit->function->call.kind & jit_call_varargs) { + if (_jit->function->call.call & jit_call_varargs) { if (jit_regno(reg) == _RAX) { reg = jit_get_reg(jit_class_gpr); jit_movr(reg, _RAX); @@ -750,6 +745,7 @@ _jit_finishr(jit_state_t *_jit, jit_int32_t r0) call->w.w = _jit->function->call.argf; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; } jit_node_t * @@ -764,13 +760,13 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0) if (_jit->function->self.alen < _jit->function->call.size) _jit->function->self.alen = _jit->function->call.size; #if __WORDSIZE == 64 - if (_jit->function->call.kind & jit_call_varargs) + if (_jit->function->call.call & jit_call_varargs) jit_regset_setbit(_jit->regarg, _RAX); reg = jit_get_reg(jit_class_gpr); node = jit_movi(reg, (jit_word_t)i0); jit_finishr(reg); jit_unget_reg(reg); - if (_jit->function->call.kind & jit_call_varargs) + if (_jit->function->call.call & jit_call_varargs) jit_regset_clrbit(_jit->regarg, _RAX); #else node = jit_calli(i0); @@ -779,6 +775,7 @@ _jit_finishi(jit_state_t *_jit, jit_pointer_t i0) #endif _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 0; return (node); } diff --git a/lib/lightning.c b/lib/lightning.c index 94a3580b1..dc9dcd9dc 100644 --- a/lib/lightning.c +++ b/lib/lightning.c @@ -725,10 +725,34 @@ void _jit_prepare(jit_state_t *_jit) { assert(_jit->function); - _jit->function->call.kind = jit_call_default; + _jit->function->call.call = jit_call_default; _jit->function->call.argi = _jit->function->call.argf = _jit->function->call.size = 0; + _jit->prepare = 1; +} + +/* If declaring a jit function as varargs, in most backends it does + * not change anything. Currently only exception is arm backend, that + * if running in hardware float abi, switches to software float abi + * if "self" function is varargs. Otherwise, there is no logic to + * handle va_list like objects that need to parse runtime state, and + * that is mainly because jit_arg* and jit_getarg* work only with + * constants values, and one must not expect them to be handled at + * runtime, they are parsed only once (same applies to jit_allocai, + * that has no jit_allocar counterpart). + */ +void +_jit_ellipsis(jit_state_t *_jit) +{ + if (_jit->prepare) { + assert(!_jit->function->call.call & jit_call_varargs); + _jit->function->call.call |= jit_call_varargs; + } + else { + assert(!_jit->function->self.call & jit_call_varargs); + _jit->function->self.call |= jit_call_varargs; + } } void