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

#include "../util/util.h"
#include "data_structs.h"
#include "cc1.h"
#include "sym.h"
#include "asm_out.h"
#include "asm.h"
#include "../util/platform.h"
#include "../util/alloc.h"
#include "sue.h"
#include "const.h"

#define SNPRINTF(s, n, ...) \
		UCC_ASSERT(snprintf(s, n, __VA_ARGS__) != n, "snprintf buffer too small")

static int label_last    = 1,
					 str_last      = 1,
					 switch_last   = 1,
					 flow_last     = 1,
					 block_last    = 1;

static const struct
{
	int sz;
	char ch;
	const char *directive;
	const char *regpre, *regpost;
} asm_type_table[] = {
	{ 1,  'b', "byte", "",  "l"  },
	{ 2,  'w', "word", "",  "x"  },
	{ 4,  'l', "long", "e", "x" },
	{ 8,  'q', "quad", "r", "x" },

	/* llong */
	{ 16,  '\0', "???", "r", "x" },

	/* ldouble */
	{ 10,  '\0', "???", "r", "x" },
};
#define ASM_TABLE_MAX 3

enum
{
	ASM_INDEX_CHAR    = 0,
	ASM_INDEX_SHORT   = 1,
	ASM_INDEX_INT     = 2,
	ASM_INDEX_LONG    = 3,
	ASM_INDEX_LLONG   = 4,
	ASM_INDEX_LDOUBLE = 5,

	ASM_INDEX_PTR = ASM_INDEX_LONG,
};


char *asm_label_block(const char *funcsp)
{
	int len;
	char *ret;

	len = strlen(funcsp) + 16;
	ret = umalloc(len);

	SNPRINTF(ret, len, "%s.block_%d", funcsp, block_last++);

	return ret;
}

char *asm_label_code(const char *fmt)
{
	int len;
	char *ret;

	len = strlen(fmt) + 10;
	ret = umalloc(len + 1);

	SNPRINTF(ret, len, ".%s.%d", fmt, label_last++);

	return ret;
}

char *asm_label_array(int str)
{
	char *ret = umalloc(16);
	SNPRINTF(ret, 16, "%s.%d", str ? "str" : "array", str_last++);
	return ret;
}

char *asm_label_static_local(const char *funcsp, const char *spel)
{
	char *ret;
	int len;

	UCC_ASSERT(funcsp, "no spel for %s", __func__);

	len = strlen(funcsp) + strlen(spel) + 9;
	ret = umalloc(len);
	SNPRINTF(ret, len, "%s.static_%s", funcsp, spel);
	return ret;
}

char *asm_label_goto(char *lbl)
{
	int len = strlen(lbl) + 6;
	char *ret = umalloc(len);
	SNPRINTF(ret, len, ".lbl_%s", lbl);
	return ret;
}

char *asm_label_case(enum asm_label_type lbltype, int val)
{
	int len;
	char *ret = umalloc(len = 15 + 32);
	switch(lbltype){
		case CASE_DEF:
			SNPRINTF(ret, len, ".case_%d_default", switch_last);
			break;

		case CASE_CASE:
		case CASE_RANGE:
		{
			const char *extra = "";
			if(val < 0){
				val = -val;
				extra = "m";
			}
			SNPRINTF(ret, len, ".case%s_%d_%s%d", lbltype == CASE_RANGE ? "_rng" : "", switch_last, extra, val);
			break;
		}
	}
	switch_last++;
	return ret;

}

char *asm_label_flow(const char *fmt)
{
	int len = 16 + strlen(fmt);
	char *ret = umalloc(len);
	SNPRINTF(ret, len, ".flow_%s_%d", fmt, flow_last++);
	return ret;
}

void asm_sym(enum asm_sym_type t, sym *s, asm_operand *reg)
{
	const int is_global = s->type == sym_global || type_store_static_or_extern(s->decl->type->store);
	char *const dsp = s->decl->spel;
	int is_auto = s->type == sym_local;
	asm_operand *brackets;
	decl *resolved_type;

	if(is_global && (t == ASM_LEA || s->decl->func_code))
		t = ASM_LEA; /* force a lea, for the label */

	if(t == ASM_LEA){
		/* decl is the ptr_depth_inc of s->decl, not s->decl */
		resolved_type = decl_ptr_depth_inc(decl_copy(s->decl));
	}else{
		resolved_type = s->decl;
	}

	if(is_global){
		brackets = asm_operand_new_label(resolved_type, dsp, 1);

	}else{
		brackets = asm_operand_new_deref(
				resolved_type,
				asm_operand_new_reg(NULL, ASM_REG_BP),
				/*((is_auto ? -1 : 2) * platform_word_size()) + s->offset); - broken? */
				(is_auto ? -1 : 1) * (((is_auto ? 1 : 2) * platform_word_size()) + s->offset));
	}

#if 0
	asm_temp(1, "%s %s, %s ; %s%s",
			t == ASM_LEA ? "lea"    : "mov",
			t == ASM_SET ? brackets : reg,
			t == ASM_SET ? reg      : brackets,
			t == ASM_LEA ? "&"      : "",
			dsp
			);
#endif

	asm_output_new(
			t == ASM_LEA   ? asm_out_type_lea : asm_out_type_mov,
			t == ASM_STORE ? brackets         : reg,
			t == ASM_STORE ? reg              : brackets);

	asm_comment("%s%s", t == ASM_LEA ? "&" : "", dsp);

	/* don't free resolved_type - it's needed by the asm_operand */
}

const char *asm_intval_str(intval *iv)
{
	static char buf[64];
	char fmt[8];
	char *p = fmt;<commit_msg>Prevent LEA for non-pointer types<commit_after>#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

#include "../util/util.h"
#include "data_structs.h"
#include "cc1.h"
#include "sym.h"
#include "asm_out.h"
#include "asm.h"
#include "../util/platform.h"
#include "../util/alloc.h"
#include "sue.h"
#include "const.h"

#define SNPRINTF(s, n, ...) \
		UCC_ASSERT(snprintf(s, n, __VA_ARGS__) != n, "snprintf buffer too small")

static int label_last    = 1,
					 str_last      = 1,
					 switch_last   = 1,
					 flow_last     = 1,
					 block_last    = 1;

static const struct
{
	int sz;
	char ch;
	const char *directive;
	const char *regpre, *regpost;
} asm_type_table[] = {
	{ 1,  'b', "byte", "",  "l"  },
	{ 2,  'w', "word", "",  "x"  },
	{ 4,  'l', "long", "e", "x" },
	{ 8,  'q', "quad", "r", "x" },

	/* llong */
	{ 16,  '\0', "???", "r", "x" },

	/* ldouble */
	{ 10,  '\0', "???", "r", "x" },
};
#define ASM_TABLE_MAX 3

enum
{
	ASM_INDEX_CHAR    = 0,
	ASM_INDEX_SHORT   = 1,
	ASM_INDEX_INT     = 2,
	ASM_INDEX_LONG    = 3,
	ASM_INDEX_LLONG   = 4,
	ASM_INDEX_LDOUBLE = 5,

	ASM_INDEX_PTR = ASM_INDEX_LONG,
};


char *asm_label_block(const char *funcsp)
{
	int len;
	char *ret;

	len = strlen(funcsp) + 16;
	ret = umalloc(len);

	SNPRINTF(ret, len, "%s.block_%d", funcsp, block_last++);

	return ret;
}

char *asm_label_code(const char *fmt)
{
	int len;
	char *ret;

	len = strlen(fmt) + 10;
	ret = umalloc(len + 1);

	SNPRINTF(ret, len, ".%s.%d", fmt, label_last++);

	return ret;
}

char *asm_label_array(int str)
{
	char *ret = umalloc(16);
	SNPRINTF(ret, 16, "%s.%d", str ? "str" : "array", str_last++);
	return ret;
}

char *asm_label_static_local(const char *funcsp, const char *spel)
{
	char *ret;
	int len;

	UCC_ASSERT(funcsp, "no spel for %s", __func__);

	len = strlen(funcsp) + strlen(spel) + 9;
	ret = umalloc(len);
	SNPRINTF(ret, len, "%s.static_%s", funcsp, spel);
	return ret;
}

char *asm_label_goto(char *lbl)
{
	int len = strlen(lbl) + 6;
	char *ret = umalloc(len);
	SNPRINTF(ret, len, ".lbl_%s", lbl);
	return ret;
}

char *asm_label_case(enum asm_label_type lbltype, int val)
{
	int len;
	char *ret = umalloc(len = 15 + 32);
	switch(lbltype){
		case CASE_DEF:
			SNPRINTF(ret, len, ".case_%d_default", switch_last);
			break;

		case CASE_CASE:
		case CASE_RANGE:
		{
			const char *extra = "";
			if(val < 0){
				val = -val;
				extra = "m";
			}
			SNPRINTF(ret, len, ".case%s_%d_%s%d", lbltype == CASE_RANGE ? "_rng" : "", switch_last, extra, val);
			break;
		}
	}
	switch_last++;
	return ret;

}

char *asm_label_flow(const char *fmt)
{
	int len = 16 + strlen(fmt);
	char *ret = umalloc(len);
	SNPRINTF(ret, len, ".flow_%s_%d", fmt, flow_last++);
	return ret;
}

void asm_sym(enum asm_sym_type t, sym *s, asm_operand *reg)
{
	const int is_global = s->type == sym_global || type_store_static_or_extern(s->decl->type->store);
	char *const dsp = s->decl->spel;
	int is_auto = s->type == sym_local;
	asm_operand *brackets;
	decl *resolved_type;

	if(is_global && (t == ASM_LEA || s->decl->func_code))
		t = ASM_LEA; /* force a lea, for the label */

	if(t == ASM_LEA){
		/* decl is the ptr_depth_inc of s->decl, not s->decl */
		resolved_type = decl_ptr_depth_inc(decl_copy(s->decl));
	}else{
		resolved_type = s->decl;
	}

	if(is_global){
		brackets = asm_operand_new_label(resolved_type, dsp, 1);

	}else{
		brackets = asm_operand_new_deref(
				resolved_type,
				asm_operand_new_reg(NULL, ASM_REG_BP),
				/*((is_auto ? -1 : 2) * platform_word_size()) + s->offset); - broken? */
				(is_auto ? -1 : 1) * (((is_auto ? 1 : 2) * platform_word_size()) + s->offset));
	}

#if 0
	asm_temp(1, "%s %s, %s ; %s%s",
			t == ASM_LEA ? "lea"    : "mov",
			t == ASM_SET ? brackets : reg,
			t == ASM_SET ? reg      : brackets,
			t == ASM_LEA ? "&"      : "",
			dsp
			);
#endif

	asm_output_new(
			t == ASM_LEA   ? asm_out_type_lea : asm_out_type_mov,
			t == ASM_STORE ? brackets         : reg,
			t == ASM_STORE ? reg              : brackets);

	asm_comment("%s%s", t == ASM_LEA ? "&" : "", dsp);

	UCC_ASSERT(t != ASM_LEA || !reg->tt, "tree type for lea");

	/* don't free resolved_type - it's needed by the asm_operand */
}

const char *asm_intval_str(intval *iv)
{
	static char buf[64];
	char fmt[8];
	char *p = fmt;
{'fraction_non_alphanumeric': 0.18499704666272887, 'fraction_numerical': 0.012522150029533373, 'mean_word_length': 3.3729338842975207, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 42, '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': '2041280', 'n_tokens_mistral': 4015, 'n_tokens_neox': 3670, 'n_words': 844}