int check_bin_op(ast::BinOp* bin_op) { assert(bin_op != nullptr); auto lhs = bin_op->left.get(); auto rhs = bin_op->right.get(); check_operation(lhs); check_operation(rhs); check_coercion(bin_op->from, lhs->type, bin_op->operator_, bin_op->id); check_coercion(bin_op->from, rhs->type, bin_op->operator_, bin_op->id); auto operators_without_coercion = std::set<std::string> {"add", "sub", "mul", "div", "and", "or"}; if(operators_without_coercion.count(bin_op->operator_) > 0) { return check_coercion(bin_op->type, bin_op->from, bin_op->operator_, bin_op->id); } auto operators_with_coercion_to_bool = std::set<std::string> {"eq", "lt"}; if(operators_with_coercion_to_bool.count(bin_op->operator_) > 0) { return check_coercion(bin_op->type, ast::types::Bool, bin_op->operator_, bin_op->id); } std::cout << "Unknown binary operation " << bin_op->operator_ << " of type "; pretty_print::type(std::cout, lhs->type); std::cout << " * "; pretty_print::type(std::cout, rhs->type); std::cout << " -> "; pretty_print::type(std::cout, bin_op->type); print_id(bin_op->id); std::cout << std::endl; return EXIT_FAILURE; }
int check_return(ast::Return* retrn) { assert(retrn != nullptr); assert(this->current_function != nullptr); auto op = retrn->value.get(); check_operation(op); return check_coercion(op->type, this->current_function->return_value, "return", retrn->id); }
int check_un_op(ast::UnOp* un_op) { assert(un_op != nullptr); auto value = un_op->value.get(); check_operation(value); switch(un_op->type) { case ast::types::Int32: if(un_op->operator_ == "neg") { return assert_type(un_op->type, value->type, un_op->operator_, un_op->id); } break; case ast::types::Float32: if(un_op->operator_ == "neg") { return assert_type(un_op->type, value->type, un_op->operator_, un_op->id); } break; case ast::types::Bool: if(un_op->operator_ == "not") { return assert_type(un_op->type, value->type, un_op->operator_, un_op->id); } break; default: break; } std::cout << "Unknown unary operation " << un_op->operator_ << " of type "; pretty_print::type(std::cout, value->type); std::cout << " -> "; pretty_print::type(std::cout, un_op-> type); print_id(un_op->id); std::cout << std::endl; return EXIT_FAILURE; }
tnfctl_errcode_t tnfctl_probe_disconnect_all(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl, void *cd) { tnf_probe_control_t *prbctl_p; boolean_t release_lock; tnfctl_errcode_t prexstat; if (hndl->mode == KERNEL_MODE) return (TNFCTL_ERR_BADARG); /*LINTED statement has no consequent: else*/ LOCK_SYNC(hndl, prexstat, release_lock); prexstat = check_operation(hndl, probe_hndl); if (prexstat) goto end_of_func; prbctl_p = &probe_hndl->probe_p->wrkprbctl; prbctl_p->probe_func = (tnf_probe_func_t) hndl->endfunc; prexstat = _tnfctl_flush_a_probe(hndl, probe_hndl->probe_p, offsetof(struct tnf_probe_control, probe_func), sizeof (tnf_probe_func_t)); end_of_func: /*LINTED statement has no consequent: else*/ UNLOCK(hndl, release_lock); return (prexstat); }
tnfctl_errcode_t tnfctl_probe_untrace(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl, void *cd) { tnf_probe_control_t *prbctl_p; boolean_t release_lock; tnfctl_errcode_t prexstat; /*LINTED statement has no consequent: else*/ LOCK_SYNC(hndl, prexstat, release_lock); prexstat = check_operation(hndl, probe_hndl); if (prexstat) goto end_of_func; prbctl_p = &probe_hndl->probe_p->wrkprbctl; prbctl_p->commit_func = (tnf_probe_func_t) hndl->rollbackfunc; prexstat = _tnfctl_flush_a_probe(hndl, probe_hndl->probe_p, offsetof(struct tnf_probe_control, commit_func), sizeof (tnf_probe_func_t)); end_of_func: /*LINTED statement has no consequent: else*/ UNLOCK(hndl, release_lock); return (prexstat); }
int check_while(ast::While* whil) { assert(whil != nullptr); auto cond = whil->condition.get(); check_operation(cond); check_coercion(cond->type, ast::types::Bool, "condition", whil->id); check_body(whil->body); return EXIT_SUCCESS; }
int check_assignment(ast::Assignment* assignment) { assert(assignment != nullptr); auto ptr = variables.find(assignment->identifier); assert_existing_variable(ptr, assignment->identifier, assignment->id); auto val = assignment->value.get(); check_operation(val); return check_coercion(val->type, ptr->getValue().type, "assignment", assignment->id); }
int check_branch(ast::Branch* branch) { assert(branch != nullptr); auto cond = branch->condition.get(); check_operation(cond); check_coercion(cond->type, ast::types::Bool, "condition", branch->id); check_body(branch->then_); check_body(branch->else_); return EXIT_SUCCESS; }
tnfctl_errcode_t tnfctl_probe_connect(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl, const char *lib_base_name, const char *func) { tnf_probe_control_t *prbctl_p; boolean_t release_lock; tnfctl_errcode_t prexstat; uintptr_t func_addr; uintptr_t comb; if (hndl->mode == KERNEL_MODE) return (TNFCTL_ERR_BADARG); /*LINTED statement has no consequent: else*/ LOCK_SYNC(hndl, prexstat, release_lock); prexstat = check_operation(hndl, probe_hndl); if (prexstat) goto end_of_func; if (func == NULL) { prexstat = TNFCTL_ERR_NONE; goto end_of_func; } if (lib_base_name) { prexstat = _tnfctl_sym_obj_find(hndl, lib_base_name, func, &func_addr); } else { prexstat = _tnfctl_sym_find(hndl, func, &func_addr); } /* check if function address was found */ if (prexstat) goto end_of_func; prbctl_p = &probe_hndl->probe_p->wrkprbctl; prexstat = _tnfctl_comb_build(hndl, PRB_COMB_CHAIN, func_addr, (uintptr_t) prbctl_p->probe_func, &comb); if (prexstat) goto end_of_func; prbctl_p->probe_func = (tnf_probe_func_t) comb; prexstat = _tnfctl_flush_a_probe(hndl, probe_hndl->probe_p, offsetof(struct tnf_probe_control, probe_func), sizeof (tnf_probe_func_t)); end_of_func: /*LINTED statement has no consequent: else*/ UNLOCK(hndl, release_lock); return (prexstat); }
int check_call(ast::Call* call) { assert(call != nullptr); auto func = functions.find(call->function_name); if(func == functions.end()) { std::cout << "Unknown function " << call->function_name << " at " << call->id << std::endl; return EXIT_FAILURE; } auto fun = func->getValue(); auto actual_argument_size = call->arguments.size(); auto prototype_argument_size = fun.arguments.size(); if(actual_argument_size < prototype_argument_size) { std::cout << "Not enough arguments to " << fun.identifier << " (expected " << prototype_argument_size << ", got " << actual_argument_size << ")" << std::endl; return EXIT_FAILURE; } if(actual_argument_size > prototype_argument_size && !fun.variadic) { std::cout << "Too many arguments to " << fun.identifier << " (expected " << prototype_argument_size << ", got " << actual_argument_size << ")" << std::endl; return EXIT_FAILURE; } check_coercion(call->type, fun.return_value, fun.identifier, call->id); for (auto it = call->arguments.begin(); it != call->arguments.end(); ++it) { auto op = it->get(); auto index = std::distance(call->arguments.begin(), it); auto prototype_op = std::next(fun.arguments.begin(), index); check_operation(op); // Variadic functions.. don't check type. if(prototype_op != fun.arguments.end()) { check_coercion(op->type, prototype_op->type, "function argument", op->id); } } return EXIT_SUCCESS; }
int check_cast(ast::Cast* cast) { assert(cast != nullptr); auto value = cast->value.get(); check_operation(value); switch(cast->type) { case ast::types::Int32: case ast::types::Float32: case ast::types::Bool: case ast::types::Void: break; default: std::cout << "Bad cast type: " << cast->type << " at " << cast->id << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
int check_void_context(ast::VoidContext* void_context) { assert(void_context != nullptr); auto op = void_context->operation.get(); check_operation(op); return check_coercion(op->type, ast::types::Void, "void context", void_context->id); }