<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "../../util/alloc.h"

#include "../type.h"
#include "../type_nav.h"

#include "../macros.h"

#include "val.h"
#include "ctx.h"
#include "virt.h"

#include "../op.h"
#include "asm.h"
#include "impl.h"
#include "out.h" /* retain/release prototypes */

#include "../cc1.h" /* cc1_type_nav */

const char *v_store_to_str(enum out_val_store store)
{
	switch(store){
		CASE_STR(V_CONST_I);
		CASE_STR(V_REG);
		CASE_STR(V_REG_SAVE);
		CASE_STR(V_LBL);
		CASE_STR(V_CONST_F);
		CASE_STR(V_FLAG);
	}
	return NULL;
}

static void v_register(out_ctx *octx, out_val *v)
{
	assert(!v->next);

	/* double link */
	v->next = octx->val_head;
	if(octx->val_head)
		octx->val_head->prev = v;

	/* store in val_head */
	octx->val_head = v;

	if(!octx->val_tail)
		octx->val_tail = v;
}

static void v_init(out_val *v, type *ty)
{
	v->retains = 1;
	v->t = ty;
}

out_val *v_new(out_ctx *octx, type *ty)
{
	out_val *v = umalloc(sizeof *v);

	v_init(v, ty);
	v_register(octx, v);

	return v;
}

static out_val *v_dup(out_ctx *octx, out_val *from, type *ty)
{
	switch(from->type){
		case V_CONST_I:
		case V_CONST_F:
		case V_LBL:
copy:
		{
			out_val *v = v_new(octx, ty);
			memcpy_safe(v, from);
			v->t = ty;
			return v;
		}

		case V_FLAG:
		{
			assert(0 && "yo");
			from = v_to_reg(octx, from);
		}

		case V_REG_SAVE:
		case V_REG:
			if(impl_reg_frame_const(&from->bits.regoff.reg))
				goto copy;
			/* copy to a new register */
		{
			struct vreg r;

			out_val_consume(
					octx,
					v_unused_reg(
						octx, /*stack backup:*/1,
						from->bits.regoff.reg.is_float, &r));

			/* dup */
			return impl_reg_cp(octx, from, &r);
		}
	}

	assert(0);
}

out_val *v_dup_or_reuse(out_ctx *octx, out_val *from, type *ty)
{
	if(!from)
		return v_new(octx, ty);

	if(from->retains > 1)
		return v_dup(octx, from, ty);

	assert(from->retains == 1);
	return from; /* reuse */
}

out_val *v_new_flag(
		out_ctx *octx, out_val *from,
		enum flag_cmp cmp, enum flag_mod mod)
{
	out_val *v = v_dup_or_reuse(octx, from,
			type_nav_btype(cc1_type_nav, type__Bool));

	v->type = V_FLAG;
	v->bits.flag.cmp = cmp;
	v->bits.flag.mods = mod;
	return v;
}

out_val *v_new_reg(
		out_ctx *octx, out_val *from,
		type *ty, const struct vreg *reg)
{
	/* reg may alias from->bits... */
	const struct vreg savedreg = *reg;
	out_val *v = v_dup_or_reuse(octx, from, ty);
	v->type = V_REG;
	memcpy_safe(&v->bits.regoff.reg, &savedreg);
	return v;
}<commit_msg>v_new_reg() fully clears the out_val::bits union<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "../../util/alloc.h"

#include "../type.h"
#include "../type_nav.h"

#include "../macros.h"

#include "val.h"
#include "ctx.h"
#include "virt.h"

#include "../op.h"
#include "asm.h"
#include "impl.h"
#include "out.h" /* retain/release prototypes */

#include "../cc1.h" /* cc1_type_nav */

const char *v_store_to_str(enum out_val_store store)
{
	switch(store){
		CASE_STR(V_CONST_I);
		CASE_STR(V_REG);
		CASE_STR(V_REG_SAVE);
		CASE_STR(V_LBL);
		CASE_STR(V_CONST_F);
		CASE_STR(V_FLAG);
	}
	return NULL;
}

static void v_register(out_ctx *octx, out_val *v)
{
	assert(!v->next);

	/* double link */
	v->next = octx->val_head;
	if(octx->val_head)
		octx->val_head->prev = v;

	/* store in val_head */
	octx->val_head = v;

	if(!octx->val_tail)
		octx->val_tail = v;
}

static void v_init(out_val *v, type *ty)
{
	v->retains = 1;
	v->t = ty;
}

out_val *v_new(out_ctx *octx, type *ty)
{
	out_val *v = umalloc(sizeof *v);

	v_init(v, ty);
	v_register(octx, v);

	return v;
}

static out_val *v_dup(out_ctx *octx, out_val *from, type *ty)
{
	switch(from->type){
		case V_CONST_I:
		case V_CONST_F:
		case V_LBL:
copy:
		{
			out_val *v = v_new(octx, ty);
			memcpy_safe(v, from);
			v->t = ty;
			return v;
		}

		case V_FLAG:
		{
			assert(0 && "yo");
			from = v_to_reg(octx, from);
		}

		case V_REG_SAVE:
		case V_REG:
			if(impl_reg_frame_const(&from->bits.regoff.reg))
				goto copy;
			/* copy to a new register */
		{
			struct vreg r;

			out_val_consume(
					octx,
					v_unused_reg(
						octx, /*stack backup:*/1,
						from->bits.regoff.reg.is_float, &r));

			/* dup */
			return impl_reg_cp(octx, from, &r);
		}
	}

	assert(0);
}

out_val *v_dup_or_reuse(out_ctx *octx, out_val *from, type *ty)
{
	if(!from)
		return v_new(octx, ty);

	if(from->retains > 1)
		return v_dup(octx, from, ty);

	assert(from->retains == 1);
	return from; /* reuse */
}

out_val *v_new_flag(
		out_ctx *octx, out_val *from,
		enum flag_cmp cmp, enum flag_mod mod)
{
	out_val *v = v_dup_or_reuse(octx, from,
			type_nav_btype(cc1_type_nav, type__Bool));

	v->type = V_FLAG;
	v->bits.flag.cmp = cmp;
	v->bits.flag.mods = mod;
	return v;
}

out_val *v_new_reg(
		out_ctx *octx, out_val *from,
		type *ty, const struct vreg *reg)
{
	/* reg may alias from->bits... */
	const struct vreg savedreg = *reg;
	out_val *v = v_dup_or_reuse(octx, from, ty);
	v->type = V_REG;
	v->bits.regoff.offset = 0;
	memcpy_safe(&v->bits.regoff.reg, &savedreg);
	return v;
}
{'fraction_non_alphanumeric': 0.17386208243797616, 'fraction_numerical': 0.003711662434069154, 'mean_word_length': 3.4483058210251953, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1022389', 'n_tokens_mistral': 2500, 'n_tokens_neox': 2319, 'n_words': 483}