int main() { //srand(time(0)); srand(50); heap *h = make_heap(); node **nodes = malloc(TESTSIZE * sizeof(node *)); for(int i = 0; i < TESTSIZE; i++) { nodes[i] = insert(h, rand() % 100); } while (h->size > 0) { make_dot(nodes, "after_inserts.dot"); getchar(); if (rand() % 2) { printf("decrease_key\n"); decrease_key(h, nodes[rand() % TESTSIZE], rand() % 100); } else { printf("delete_min\n"); delete_min(h); } if (h->size > 0) printf("heap size = %d and root key = %d\n", h->size, h->root->key); } free(nodes); return 1; }
/*! \brief Fixes references to struct pointers that have become unions. * * \param e * the Expr to process. * \param data * used to pass in the interprocedural symbol table. * * This function is indended to be applied postorder. * * If \a e is a OP_arrow or OP_dot that now refers to a union that was * created to hold pointers to different structs with the same name, * add an OP_dot to get the correct pointer out of the union. * * When we inserted the union, types that were previously struct pointers * became unions. This corrupted the Expr tree as far as determining * expression type, as we might now be treating a union as a union pointer. * * This function processes all children first, so by the time we look at * \a e, the Expr tree below \a e is mostly valid. */ static void fix_multi_ref (Expr e, void *data) { SymbolTable ip_table = (SymbolTable)data; Key expr_type, scope_key; if (e) { scope_key = PST_GetExprScope (ip_table, e); expr_type = PST_ExprType (ip_table, e); if (is_multi_type (ip_table, expr_type) && \ !(PST_GetTypeQualifier (ip_table, expr_type) & TY_CONST)) e = make_dot (ip_table, e, expr_type, scope_key); } return; }
/*! \brief Validates a return statement. * * \param s * the Stmt to validate. * \param data * a pointer to a validate_arg struct. * * If \a s is a return statement, this function validates the expression * returned to make sure its type is as specified in the function's prototype. */ static void validate_return (Stmt s, void *data) { validate_arg *arg = (validate_arg *)data; FuncDcl parent_func; Type return_type, expr_type; bool return_is_multi, return_is_pointer, expr_is_multi, expr_is_pointer; Expr ret; if (P_GetStmtType (s) == ST_RETURN && (ret = P_GetStmtRet (s))) { /* Find the return's parent FuncDcl. */ parent_func = PST_GetStmtParentFunc (arg->ip_table, s); return_type = PST_GetTypeType (arg->ip_table, P_GetFuncDclType (parent_func)); expr_type = PST_ExprType (arg->ip_table, ret); return_is_multi = is_multi_type (arg->ip_table, return_type); return_is_pointer = is_pointer_type (arg->ip_table, return_type); expr_is_multi = is_multi_type (arg->ip_table, expr_type); expr_is_pointer = is_pointer_type (arg->ip_table, expr_type); if (return_is_multi && !expr_is_multi) { /* Build (t.field = cur_arg, t) */ make_struct_pointer_multi (arg->ip_table, return_type, ret); arg->must_flatten = TRUE; } else if (return_is_multi && expr_is_pointer) { /* Build (arg.field). */ ret = make_dot (arg->ip_table, ret, expr_type, PST_GetFuncDclScope (arg->ip_table, parent_func)); arg->must_flatten = TRUE; } } return; }
/*! \brief Validates a function call. * * \param e * the Expr to inspect. * \param data * a pointer to a validate_arg struct. * * Validates the arguments to a function call against the called * function's param types. If a parameter is of a multi type union, * the correct field is selected. If the call has too many or too few * arguments, this is corrected */ static void validate_call (Expr e, void *data) { validate_arg *arg = (validate_arg *)data; Expr callee_expr, cur_arg, next_arg; FuncDcl func; Key func_scope_key; Type func_type, param_type, cur_arg_type; Param param; if (e && P_GetExprOpcode (e) == OP_call) { /* Get the callee function's type. */ callee_expr = P_GetExprOperands (e); func_type = PST_ExprType (arg->ip_table, P_GetExprOperands (e)); /* We can only validate direct calls of defined functions. */ if (P_IsIndirectFunctionCall (e)) { func_scope_key = PST_GetScopeFromEntryKey (arg->ip_table, func_type); /* If we have an indirect call with unspecified parameters, we * can't do anything more. */ if (PST_GetTypeParam (arg->ip_table, func_type) == NULL) return; } else if (P_IsDirectFunctionCall (e)) { func = PST_GetFuncDclEntry (arg->ip_table, P_GetExprVarKey (callee_expr)); if (!P_TstFuncDclQualifier (func, VQ_DEFINED) || \ P_TstFuncDclQualifier (func, VQ_APP_ELLIPSIS)) goto done; func_scope_key = \ PST_GetScopeFromEntryKey (arg->ip_table, P_GetExprVarKey (callee_expr)); } if (!PST_IsFunctionType (arg->ip_table, func_type)) P_punt ("validate.c:validate_call:%d e does not result in a\n" "function type (%d, %d)", __LINE__, func_type.file, func_type.sym); /* Loop through the call arguments and the function parameters to * determine if we need to do anything. */ cur_arg = P_GetExprSibling (callee_expr); param = PST_GetTypeParam (arg->ip_table, func_type); while (cur_arg && param) { bool arg_is_multi, arg_is_pointer, param_is_multi, param_is_pointer; next_arg = P_GetExprNext (cur_arg); param_type = P_GetParamKey (param); cur_arg_type = PST_ExprType (arg->ip_table, cur_arg); /* If the current param is a vararg, the call does not require * repair. */ if (PST_IsVarargType (arg->ip_table, param_type)) goto done; arg_is_multi = is_multi_type (arg->ip_table, cur_arg_type); arg_is_pointer = is_pointer_type (arg->ip_table, cur_arg_type); param_is_multi = is_multi_type (arg->ip_table, param_type); param_is_pointer = is_pointer_type (arg->ip_table, param_type); if (param_is_pointer && arg_is_pointer) { /* Build (t.field1 = cur_arg, t).field2 */ TypeDcl td = PST_GetTypeTypeDcl (arg->ip_table, param_type); Type multi_type = Plink_GetTypeDclMultiType (td); cur_arg = make_struct_pointer_multi (arg->ip_table, multi_type, cur_arg); cur_arg = make_dot (arg->ip_table, cur_arg, multi_type, func_scope_key); arg->must_flatten = TRUE; } else if (param_is_pointer && arg_is_multi) { /* Build (arg.field). */ cur_arg = make_dot (arg->ip_table, cur_arg, cur_arg_type, func_scope_key); arg->must_flatten = TRUE; } else if (param_is_multi && !arg_is_multi) { /* Build (t.field = cur_arg, t) */ make_struct_pointer_multi (arg->ip_table, param_type, cur_arg); arg->must_flatten = TRUE; } else { /* If the argument type doesn't match the parameter type, cast * it. */ if (PST_IsPointerType (arg->ip_table, param_type) && \ PST_IsIntegralType (arg->ip_table, cur_arg_type)) { Key scope_key = PST_GetExprScope (arg->ip_table, cur_arg); Expr cast = PST_ScopeNewExprWithOpcode (arg->ip_table, scope_key, OP_cast); P_ExprSwap (&cur_arg, &cast); P_AppendExprOperands (cast, cur_arg); PST_SetExprType (arg->ip_table, cast, param_type); } } cur_arg = next_arg; param = P_GetParamNext (param); } if (cur_arg || param) { if (cur_arg) { /* If there are too many arguments, we need to remove extra ones * from the end. */ e->pragma = \ P_AppendPragmaNext (e->pragma, P_NewPragmaWithSpecExpr ("PLV_REMOVE", NULL)); remove_args (arg->ip_table, e, cur_arg); arg->must_flatten = TRUE; } else if (param) { /* If there are too few arguments, we need to add extras to pad * the call. */ e->pragma = \ P_AppendPragmaNext (e->pragma, P_NewPragmaWithSpecExpr ("PLV_ADD", NULL)); add_args (arg->ip_table, e, param); } } } done: return; }