JIT compiler support for embedded array and structures variables.

[INTERPRETER]
* NEW: JIT compiler support for embedded array and structures variables.

[GB.JIT]
* NEW: JIT compiler support for embedded array and structures variables.
This commit is contained in:
gambas 2021-06-18 04:33:42 +02:00
parent b0ac35dd4b
commit 78ad25231b
5 changed files with 180 additions and 97 deletions

View file

@ -111,6 +111,7 @@ typedef
void *(*get_array_class)(void *cp, JIT_CTYPE ctype);
void (*add_string_local)(GB_STRING *str, GB_STRING val);
void (*add_string_global)(char **str, GB_STRING val);
void (*value_class_write)(void *class, GB_VALUE *value, void *addr, JIT_CTYPE ctype);
}
JIT_INTERFACE;

View file

@ -384,6 +384,7 @@ const void *const GAMBAS_JitApi[] =
(void *)CARRAY_get_array_class,
(void *)JIT_add_string_local,
(void *)JIT_add_string_global,
(void *)VALUE_class_write,
NULL
};

View file

@ -112,7 +112,11 @@ Public Sub _Compile(sArch As String) As Boolean
If Not _ClassStat.HasFast Then Continue
sFile = _ClassStat.Name
If $bDebug Then Error "gb.jit: translating class "; sFile
Print #hFile, __Jit.Translate(sFile, sArch)
If $bDebug Then
Print #hFile, Replace(__Jit.Translate(sFile, sArch), ";", ";\n")
Else
Print #hFile, __Jit.Translate(sFile, sArch)
Endif
Next
Close #hFile

View file

@ -355,12 +355,9 @@ enum
#define GET_o(_addr, _type) GET_OBJECT((*(char **)(_addr)), _type)
#define GET_v(_addr) GET_VARIANT((*(GB_VARIANT_VALUE *)(_addr)))
#define GET_S(_ref, _addr, _type) GET_OBJECT(JIT.static_struct((_ref), (_type), (_addr)), _type)
#define GET_A(_class, _ref, _addr, _type, _desc) ({ \
SP = sp; \
GB.Unref(&ra); \
ra = JIT.static_array((_class), (_ref), (void *)(_desc), (_addr)); \
GET_OBJECT(ra, _type); \
GET_OBJECT(JIT.static_array((_class), (_ref), (void *)(_desc), (_addr)), _type); \
})
#define SET_b(_addr, _val) (GET_b(_addr) = ((_val) ? -1 : 0))
@ -375,6 +372,13 @@ enum
#define SET_s(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreString((GB_STRING *)&temp, (char **)(_addr)); })
#define SET_o(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreObject((GB_OBJECT *)&temp, (void **)(_addr)); })
#define SET_v(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreVariant((GB_VARIANT *)&temp, (GB_VARIANT_VALUE *)(_addr)); })
#define SET_SA(_class, _addr, _ctype, _val) ({ \
GB_VALUE temp = (GB_VALUE)(_val); \
int ctype = (_ctype); \
GB.BorrowValue(&temp); \
JIT.value_class_write((_class), &temp, (_addr), *(JIT_CTYPE *)&ctype); \
GB.ReleaseValue(&temp); \
})
#define GET_ARRAY_UNSAFE(_type, _array, _index) ({ \
GB_ARRAY_IMPL *_a = (_array).value; \

View file

@ -853,6 +853,87 @@ static void push_function(int func, int index)
}
static void push_static_variable(CLASS *class, CTYPE ctype, char *addr)
{
TYPE type = JIT_ctype_to_type(class, ctype);
char class_name[32];
if (class == JIT_class)
strcpy(class_name, "CP");
else
sprintf(class_name, "CLASS(%p)", class);
switch(ctype.id)
{
case TC_STRUCT:
if (class == JIT_class)
push(type, "GET_S(CP, %p, CLASS(%p))", addr, (CLASS *)type);
else
push(type, "GET_S(CLASS(%p), %p, CLASS(%p))", class, addr, (CLASS *)type);
break;
case TC_ARRAY:
//declare(&_decl_ra, "void *ra = NULL");
if (class == JIT_class)
push(type, "GET_A(CP, CP, %p, CLASS(%p), %p)", addr, (CLASS *)type, class->load->array[ctype.value]);
else
push(type, "GET_A(CLASS(%p), %p, %p, CLASS(%p), %p)", class, class, addr, (CLASS *)type, class->load->array[ctype.value]);
break;
case T_OBJECT:
if (class == JIT_class)
{
if (TYPE_is_pure_object(type))
push(type, "GET_o(%p, CLASS(%p))", addr, (CLASS *)type);
else
push(type, "GET_o(%p, GB_T_OBJECT)", addr);
}
else
{
if (TYPE_is_pure_object(type))
push(type, "({ JIT.load_class(%p); GET_o(%p, CLASS(%p)); })", class, addr, (CLASS *)type);
else
push(type, "({ JIT.load_class(%p); GET_o(%p, GB_T_OBJECT); })", class, addr);
}
break;
default:
if (class == JIT_class)
push(type, "GET_%s(%p)", JIT_get_type(type), addr);
else
push(type, "({ JIT.load_class(%p); GET_%s(%p); })", class, JIT_get_type(type), addr);
}
}
static void push_dynamic_variable(CLASS *class, CTYPE ctype, int pos, char *addr)
{
TYPE type = JIT_ctype_to_type(class, ctype);
switch(ctype.id)
{
case TC_STRUCT:
push(type, "GET_S(%s, %s + %d, CLASS(%p))", addr, addr, pos, (CLASS *)type);
break;
case TC_ARRAY:
//declare(&_decl_ra, "void *ra = NULL");
push(type, "GET_A(%p, %s, %s + %d, CLASS(%p), %p)", class, addr, addr, pos, (CLASS *)type, class->load->array[ctype.value]);
break;
case T_OBJECT:
if (TYPE_is_pure_object(type))
push(type, "GET_o(%s + %d, CLASS(%p))", addr, pos, (CLASS *)type);
else
push(type, "GET_o(%s + %d, GB_T_OBJECT)", addr, pos);
break;
default:
push(type, "GET_%s(%s + %d)", JIT_get_type(type), addr, pos);
}
}
static void push_unknown(int index)
{
TYPE type = T_UNKNOWN;
@ -874,7 +955,7 @@ static void push_unknown(int index)
CLASS_DESC *desc;
void *addr;
int pos;
TYPE utype;
CTYPE ctype;
char *sym;
char *get_addr;
bool static_class;
@ -910,21 +991,12 @@ static void push_unknown(int index)
{
case CD_STATIC_VARIABLE:
utype = JIT_ctype_to_type(class, desc->variable.ctype);
pop_stack(1);
ctype = desc->variable.ctype;
addr = (char *)desc->variable.class->stat + desc->variable.offset;
if (TYPE_is_object(utype))
{
if (TYPE_is_pure_object(utype))
push(utype, "({ JIT.load_class(%p); GET_o(%p, CLASS(%p)); })", class, addr, (CLASS *)utype);
else
push(utype, "({ JIT.load_class(%p); GET_o(%p, GB_T_OBJECT); })", class, addr);
}
else
push(utype, "({ JIT.load_class(%p); GET_%s(%p); })", class, JIT_get_type(utype), addr);
push_static_variable(class, ctype, addr);
return;
@ -932,7 +1004,7 @@ static void push_unknown(int index)
// TODO: automatic class
utype = JIT_ctype_to_type(class, desc->variable.ctype);
ctype = desc->variable.ctype;
expr = peek(-1, (TYPE)class);
@ -947,15 +1019,7 @@ static void push_unknown(int index)
pop_stack(1);
if (TYPE_is_object(utype))
{
if (TYPE_is_pure_object(utype))
push(utype, "GET_o(%s + %d, CLASS(%p))", get_addr, pos, (CLASS *)utype);
else
push(utype, "GET_o(%s + %d, GB_T_OBJECT)", get_addr, pos);
}
else
push(utype, "GET_%s(%s + %d)", JIT_get_type(utype), get_addr, pos);
push_dynamic_variable(class, ctype, pos, get_addr);
STR_free(get_addr);
@ -1021,6 +1085,70 @@ static void push_unknown(int index)
}
static void pop_static_variable(CLASS *class, CTYPE ctype, char *addr)
{
TYPE type = JIT_ctype_to_type(class, ctype);
char *klass;
if (class == JIT_class)
klass = "CP";
else
klass = STR_print("CLASS(%p)", class);
_no_release = TRUE;
switch(ctype.id)
{
case TC_STRUCT:
case TC_ARRAY:
if (check_swap(type, "SET_SA(%s, %p, %d, %%s)", klass, addr, ctype))
pop(type, "SET_SA(%s, %p, %d, %%s)", klass, addr, ctype);
break;
default:
if (check_swap(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr))
pop(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr);
}
_no_release = FALSE;
}
static void pop_dynamic_variable(CLASS *class, CTYPE ctype, int pos, char *addr)
{
TYPE type = JIT_ctype_to_type(class, ctype);
char *klass;
if (class == JIT_class)
klass = "CP";
else
klass = STR_print("CLASS(%p)", class);
_no_release = TRUE;
switch(ctype.id)
{
case TC_STRUCT:
case TC_ARRAY:
if (check_swap(type, "SET_SA(%s, %s + %d, %d, %%s)", klass, addr, pos, ctype))
pop(type, "SET_SA(%s, %s + %d, %d, %%s)", klass, addr, pos, ctype);
break;
default:
if (check_swap(type, "SET_%s(%s + %d, %%s)", JIT_get_type(type), addr, pos))
pop(type, "SET_%s(%s + %d, %%s)", JIT_get_type(type), addr, pos);
}
_no_release = FALSE;
}
static void pop_unknown(int index)
{
CLASS *class;
@ -1036,7 +1164,7 @@ static void pop_unknown(int index)
CLASS_DESC *desc;
void *addr;
int pos;
TYPE utype;
CTYPE ctype;
const char *sym;
char *get_addr;
@ -1050,16 +1178,12 @@ static void pop_unknown(int index)
{
case CD_STATIC_VARIABLE:
utype = JIT_ctype_to_type(class, desc->variable.ctype);
pop_stack(1);
ctype = desc->variable.ctype;
addr = (char *)desc->variable.class->stat + desc->variable.offset;
_no_release = TRUE;
if (check_swap(utype, "SET_%s(%p, %%s)", JIT_get_type(utype), addr))
pop(utype, "SET_%s(%p, %%s)", JIT_get_type(utype), addr);
_no_release = FALSE;
pop_static_variable(class, ctype, addr);
return;
@ -1067,7 +1191,7 @@ static void pop_unknown(int index)
// TODO: automatic class
utype = JIT_ctype_to_type(class, desc->variable.ctype);
ctype = desc->variable.ctype;
expr = peek(-1, (TYPE)class);
@ -1082,10 +1206,7 @@ static void pop_unknown(int index)
pos = desc->variable.offset;
_no_release = TRUE;
if (check_swap(utype, "SET_%s(%s + %d, %%s)", JIT_get_type(utype), get_addr, pos))
pop(utype, "SET_%s(%s + %d, %%s)", JIT_get_type(utype), get_addr, pos);
_no_release = FALSE;
pop_dynamic_variable(class, ctype, pos, get_addr);
STR_free(get_addr);
@ -1132,7 +1253,7 @@ static void push_array(ushort code)
//JIT_print(" // %s %d\n", class->name, class->is_array);
if (class->is_array)
if (class->is_array && !class->is_array_of_struct)
{
type = class->array_type;
@ -1198,7 +1319,7 @@ static void pop_array(ushort code)
{
CLASS *class = (CLASS *)type;
if (class->is_array)
if (class->is_array && !class->is_array_of_struct)
{
type = class->array_type;
@ -2869,43 +2990,19 @@ _PUSH_STATIC:
index = GET_7XX();
ctype = class->load->stat[index].type;
type = JIT_ctype_to_type(class, ctype);
addr = &class->stat[class->load->stat[index].pos];
switch(ctype.id)
{
case TC_STRUCT:
push(type, "GET_S(CP, %p, CLASS(%p))", addr, (CLASS *)type);
break;
case TC_ARRAY:
declare(&_decl_ra, "void *ra = NULL");
push(type, "GET_A(CP, CP, %p, CLASS(%p), %p)", addr, (CLASS *)type, JIT_class->load->array[ctype.value]);
break;
case T_OBJECT:
if (TYPE_is_pure_object(type))
push(type, "GET_o(%p, CLASS(%p))", addr, (CLASS *)type);
else
push(type, "GET_o(%p, GB_T_OBJECT)", addr);
break;
default:
push(type, "GET_%s(%p)", JIT_get_type(type), addr);
}
push_static_variable(JIT_class, ctype, addr);
goto _MAIN;
_POP_STATIC:
index = GET_7XX();
type = JIT_ctype_to_type(class, class->load->stat[index].type);
ctype = class->load->stat[index].type;
addr = &class->stat[class->load->stat[index].pos];
_no_release = TRUE;
if (check_swap(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr))
pop(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr);
_no_release = FALSE;
pop_static_variable(JIT_class, ctype, addr);
goto _MAIN;
@ -2914,42 +3011,18 @@ _PUSH_DYNAMIC:
index = GET_7XX();
pos = class->load->dyn[index].pos;
ctype = class->load->dyn[index].type;
type = JIT_ctype_to_type(class, ctype);
switch(ctype.id)
{
case TC_STRUCT:
push(type, "GET_S(OP, &OP[%d], CLASS(%p))", pos, (CLASS *)type);
break;
case TC_ARRAY:
declare(&_decl_ra, "void *ra = NULL");
push(type, "GET_A(CP, OP, &OP[%d], CLASS(%p), %p)", pos, (CLASS *)type, JIT_class->load->array[ctype.value]);
break;
case T_OBJECT:
if (TYPE_is_pure_object(type))
push(type, "GET_o(&OP[%d], CLASS(%p))", pos, (CLASS *)type);
else
push(type, "GET_o(&OP[%d], GB_T_OBJECT)", pos);
break;
default:
push(type, "GET_%s(&OP[%d])", JIT_get_type(type), pos);
}
push_dynamic_variable(JIT_class, ctype, pos, "OP");
goto _MAIN;
_POP_DYNAMIC:
index = GET_7XX();
type = JIT_ctype_to_type(class, class->load->dyn[index].type);
pos = class->load->dyn[index].pos;
ctype = class->load->dyn[index].type;
_no_release = TRUE;
if (check_swap(type, "SET_%s(&OP[%d], %%s)", JIT_get_type(type), pos))
pop(type, "SET_%s(&OP[%d], %%s)", JIT_get_type(type), pos);
_no_release = FALSE;
pop_dynamic_variable(JIT_class, ctype, pos, "OP");
goto _MAIN;