RZ_API RzAnalysisVar *rz_analysis_function_set_var(RzAnalysisFunction *fcn, int delta, char kind, RZ_BORROW RZ_NULLABLE const RzType *type, int size, bool isarg, RZ_NONNULL const char *name) {
	rz_return_val_if_fail(fcn && name, NULL);
	RzAnalysisVar *existing = rz_analysis_function_get_var_byname(fcn, name);
	if (existing && (existing->kind != kind || existing->delta != delta)) {
		// var name already exists at a different kind+delta
		return NULL;
	}
	RzRegItem *reg = NULL;
	if (!kind) {
		kind = RZ_ANALYSIS_VAR_KIND_BPV;
	}
	switch (kind) {
	case RZ_ANALYSIS_VAR_KIND_BPV: // base pointer var/args
	case RZ_ANALYSIS_VAR_KIND_SPV: // stack pointer var/args
	case RZ_ANALYSIS_VAR_KIND_REG: // registers args
		break;
	default:
		eprintf("Invalid var kind '%c'\n", kind);
		return NULL;
	}
	if (kind == RZ_ANALYSIS_VAR_KIND_REG) {
		reg = rz_reg_index_get(fcn->analysis->reg, RZ_ABS(delta));
		if (!reg) {
			eprintf("Register wasn't found at the given delta\n");
			return NULL;
		}
	}
	RzAnalysisVar *var = rz_analysis_function_get_var(fcn, kind, delta);
	if (!var) {
		var = RZ_NEW0(RzAnalysisVar);
		if (!var) {
			return NULL;
		}
		rz_pvector_push(&fcn->vars, var);
		var->fcn = fcn;
		rz_vector_init(&var->accesses, sizeof(RzAnalysisVarAccess), NULL, NULL);
		rz_vector_init(&var->constraints, sizeof(RzTypeConstraint), NULL, NULL);
	} else {
		free(var->name);
		free(var->regname);
		if (var->type != type) {
			// only free if not assigning the own type to itself
			rz_type_free(var->type);
			var->type = NULL;
		}
	}
	var->name = strdup(name);
	var->regname = reg ? strdup(reg->name) : NULL; // TODO: no strdup here? pool? or not keep regname at all?
	if (!var->type || var->type != type) {
		// only clone if we don't already own this type (and didn't free it above)
		var->type = var_type_clone_or_default_type(fcn->analysis, type, size);
	}
	var->kind = kind;
	var->isarg = isarg;
	var->delta = delta;
	resolve_var_overlaps(var);
	return var;
}
RZ_API RzAnalysisVar *rz_analysis_function_set_var(RzAnalysisFunction *fcn, int delta, char kind, RZ_BORROW RZ_NULLABLE const RzType *type, int size, bool isarg, RZ_NONNULL const char *name) {
	rz_return_val_if_fail(fcn && name, NULL);
	RzAnalysisVar *existing = rz_analysis_function_get_var_byname(fcn, name);
	if (existing && (existing->kind != kind || existing->delta != delta)) {
		 
		return NULL;
	}
	RzRegItem *reg = NULL;
	if (!kind) {
		kind = RZ_ANALYSIS_VAR_KIND_BPV;
	}
	switch (kind) {
	case RZ_ANALYSIS_VAR_KIND_BPV:  
	case RZ_ANALYSIS_VAR_KIND_SPV:  
	case RZ_ANALYSIS_VAR_KIND_REG:  
		break;
	default:
		eprintf("Invalid var kind '%c'\n", kind);
		return NULL;
	}
	if (kind == RZ_ANALYSIS_VAR_KIND_REG) {
		reg = rz_reg_index_get(fcn->analysis->reg, RZ_ABS(delta));
		if (!reg) {
			eprintf("Register wasn't found at the given delta\n");
			return NULL;
		}
	}
	RzAnalysisVar *var = rz_analysis_function_get_var(fcn, kind, delta);
	if (!var) {
		var = RZ_NEW0(RzAnalysisVar);
		if (!var) {
			return NULL;
		}
		rz_pvector_push(&fcn->vars, var);
		var->fcn = fcn;
		rz_vector_init(&var->accesses, sizeof(RzAnalysisVarAccess), NULL, NULL);
		rz_vector_init(&var->constraints, sizeof(RzTypeConstraint), NULL, NULL);
	} else {
		free(var->name);
		free(var->regname);
		if (var->type != type) {
			 
			rz_type_free(var->type);
			var->type = NULL;
		}
	}
	var->name = strdup(name);
	var->regname = reg ? strdup(reg->name) : NULL;  
	if (!var->type || var->type != type) {
		 
		var->type = var_type_clone_or_default_type(fcn->analysis, type, size);
	}
	var->kind = kind;
	var->isarg = isarg;
	var->delta = delta;
	resolve_var_overlaps(var);
	return var;
}