static void add_rmethod_to_subtype(reach_t* r, reach_type_t* t, reach_method_name_t* n, reach_method_t* m, pass_opt_t* opt) { // Add the method to the type if it isn't already there. reach_method_name_t* n2 = add_method_name(t, n->name); add_rmethod(r, t, n2, m->cap, m->typeargs, opt); // Add this mangling to the type if it isn't already there. reach_method_t* mangled = reach_mangled_get(&n2->r_mangled, m); if(mangled != NULL) return; mangled = POOL_ALLOC(reach_method_t); memset(mangled, 0, sizeof(reach_method_t)); mangled->name = m->name; mangled->mangled_name = m->mangled_name; mangled->full_name = make_full_name(t, mangled); mangled->cap = m->cap; mangled->r_fun = ast_dup(m->r_fun); mangled->typeargs = ast_dup(m->typeargs); mangled->forwarding = true; mangled->param_count = m->param_count; mangled->params = (reach_param_t*)ponyint_pool_alloc_size( mangled->param_count * sizeof(reach_param_t)); memcpy(mangled->params, m->params, m->param_count * sizeof(reach_param_t)); mangled->result = m->result; // Add to the mangled table only. reach_mangled_put(&n2->r_mangled, mangled); }
static reach_method_t* add_rmethod(reach_t* r, reach_type_t* t, reach_method_name_t* n, token_id cap, ast_t* typeargs, pass_opt_t* opt) { const char* name = genname_fun(cap, n->name, typeargs); reach_method_t* m = reach_rmethod(n, name); if(m != NULL) return m; m = POOL_ALLOC(reach_method_t); memset(m, 0, sizeof(reach_method_t)); m->name = name; m->cap = cap; m->typeargs = ast_dup(typeargs); m->vtable_index = (uint32_t)-1; ast_t* r_ast = set_cap_and_ephemeral(t->ast, cap, TK_NONE); ast_t* fun = lookup(NULL, NULL, r_ast, n->name); ast_free_unattached(r_ast); if(typeargs != NULL) { // Reify the method with its typeargs, if it has any. AST_GET_CHILDREN(fun, cap, id, typeparams, params, result, can_error, body); fun = reify(fun, typeparams, typeargs, opt, false); } m->r_fun = fun; set_method_types(r, m, opt); m->mangled_name = make_mangled_name(m); m->full_name = make_full_name(t, m); // Add to both tables. reach_methods_put(&n->r_methods, m); reach_mangled_put(&n->r_mangled, m); // Put on a stack of reachable methods to trace. r->stack = reach_method_stack_push(r->stack, m); // Add the method to any subtypes. add_rmethod_to_subtypes(r, t, n, m, opt); return m; }
/* size has to be big enough to store a '@', a '\0' * and the var or row number. */ void lps_makename( char* target, int size, const char* name, int no) { char temp[9]; int len; int nlen; assert(target != NULL); assert(size > MIN_NAME_LEN); /* 8+1, so we have at least '@' + 7 digits + '\0' */ assert(name != NULL); assert(no >= -1); assert(no <= 0xFFFFFFF); /* 7 hex digits = 268,435,455 */ nlen = (int)strlen(name); /* There are 3 possibilities: * * i) name is smaller than size and does not contain problematic chars * -> just copy it. * ii) as above but contains unvalid chars * -> copy it, transform the chars to '_' and append "@varnum". * iii) the name is longer than the size. * -> do as in ii) but only copy as much chars as fit. * iv) no == -1 * -> generate a full human readable name */ if (no == -1) make_full_name(target, size, name); else if (nlen < size) { if (lpfstrncpy(target, name, nlen)) { sprintf(temp, "@%x", no); len = size - (int)strlen(temp) - 1; assert(len >= 0); /* Trick: if len > strlen(target) it doesn't matter, * lpfstrncmp always appends a '\0' and the strcat below * will append temp at the right place. * Otherwise it will be appended at len, which is the * latest possible position. */ target[len] = '\0'; strcat(target, temp); } } else { sprintf(temp, "@%x", no); len = size - (int)strlen(temp) - 1; /* -1 for '\0' */ assert(len >= 0); (void)lpfstrncpy(target, name, len); strcat(target, temp); } assert(strlen(target) <= (size_t)size - 1); }