<commit_before>/* See LICENSE file for copyright and license details. */
static char sccsid[] = "@(#) ./cc1/code.c";
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "../inc/cc.h"
#include "cc1.h"

static void emitbin(unsigned, void *),
            emitcast(unsigned, void *),
            emitsym(unsigned, void *),
            emitexp(unsigned, void *),
            emitsymid(unsigned, void *),
            emittext(unsigned, void *),
            emitfun(unsigned, void *),
            emitdcl(unsigned, void *),
            emitinit(unsigned, void *),
            emittype(unsigned, void *);

char *optxt[] = {
	[OADD] = "+",
	[OSUB] = "-",
	[OMUL] = "*",
	[OINC] = ":i",
	[ODEC] =  ":d",
	[OPTR] = "@",
	[OMOD] = "%",
	[ODIV] = "/",
	[OSHL] = "l",
	[OSHR]  = "r",
	[OLT] = "<",
	[OGT] = ">",
	[OGE] = "]",
	[OLE] =  "[",
	[OEQ] = "=",
	[ONE] = "!",
	[OBAND] = "&",
	[OBXOR]  = "^",
	[OBOR] = "|",
	[OASSIGN] = ":",
	[OA_MUL] = ":*",
	[OA_DIV] = ":/",
	[OA_MOD] = ":%",
	[OA_ADD] = ":+",
	[OA_SUB] = ":-",
	[OA_SHL] = ":l",
	[OA_SHR] = ":r",
	[OA_AND] = ":&",
	[OA_XOR] = ":^",
	[OA_OR] = ":|",
	[OADDR] = "'",
	[OSNEG] = "_",
	[ONEG] = "n",
	[OCPL] = "~",
	[OAND] = "a",
	[OOR] = "o",
	[OASK] = "?",
	[OCOMMA] = ",",
	[OLABEL] = "L%d\n",
	[ODEFAULT] = "\tf\tL%d\n",
	[OBSWITCH] = "\ts",
	[OESWITCH] = "\tt\tL%d\n",
	[OCASE] = "\tv\tL%d",
	[OJUMP] = "\tj\tL%d\n",
	[OBRANCH] = "\ty\tL%d",
	[OEFUN] = "}\n",
	[OELOOP] = "\tb\n",
	[OBLOOP] = "\te\n",
	[ORET] = "\th",
	[OPAR] = "p",
	[OCALL] = "c",
	[OFIELD] = "."
};

void (*opcode[])(unsigned, void *) = {
	[OADD] = emitbin,
	[OSUB] = emitbin,
	[OMUL] = emitbin,
	[OINC] = emitbin,
	[ODEC] =  emitbin,
	[OPTR] = emitbin,
	[OMOD] = emitbin,
	[ODIV] = emitbin,
	[OSHL] = emitbin,
	[OSHR]  = emitbin,
	[OLT] = emitbin,
	[OGT] = emitbin,
	[OGE] = emitbin,
	[OLE] =  emitbin,
	[OEQ] = emitbin,
	[ONE] = emitbin,
	[OBAND] = emitbin,
	[OBXOR]  = emitbin,
	[OBOR] = emitbin,
	[OASSIGN] = emitbin,
	[OA_MUL] = emitbin,
	[OA_DIV] = emitbin,
	[OA_MOD] = emitbin,
	[OA_ADD] = emitbin,
	[OA_SUB] = emitbin,
	[OA_SHL] = emitbin,
	[OA_SHR] = emitbin,
	[OA_AND] = emitbin,
	[OA_XOR] = emitbin,
	[OA_OR] = emitbin,
	[OADDR] = emitbin,
	[OSNEG] = emitbin,
	[ONEG] = emitbin,
	[OCPL] = emitbin,
	[OAND] = emitbin,
	[OOR] = emitbin,
	[OCOMMA] = emitbin,
	[OCAST] = emitcast,
	[OSYM] = emitsym,
	[OASK] = emitbin,
	[OCOLON] = emitbin,
	[OFIELD]= emitbin,
	[OEXPR] = emitexp,
	[OLABEL] = emitsymid,
	[ODEFAULT] = emitsymid,
	[OCASE] = emitsymid,
	[OJUMP] = emitsymid,
	[OBRANCH] = emitsymid,
	[OEFUN] = emittext,
	[OELOOP] = emittext,
	[OBLOOP] = emittext,
	[OFUN] = emitfun,
	[ORET] = emittext,
	[ODECL] = emitdcl,
	[OBSWITCH] = emittext,
	[OESWITCH] = emitsymid,
	[OPAR] = emitbin,
	[OCALL] = emitbin,
	[OINIT] = emitinit,
	[OTYP] = emittype,
};

void
freetree(Node *np)
{
	if (!np)
		return;
	freetree(np->left);
	freetree(np->right);
	free(np);
}

static void
emitnode(Node *np)
{
	if (np)
		(*opcode[np->op])(np->op, np);
}

void
emit(unsigned op, void *arg)
{
	extern int failure;

	if (failure)
		return;
	(*opcode[op])(op, arg);
}

static void
emitvar(Symbol *sym)
{
	char c;
	short flags = sym->flags;

	if (flags & SLOCAL)
		c = 'T';
	else if (flags & SPRIVATE)
		c =  'Y';
	else if (flags & SGLOBAL)
		c = 'G';
	else if (flags & SREGISTER)
		c = 'R';
	else if (flags & SFIELD)
		c = 'M';
	else if (flags & SEXTERN)
		c = 'X';
	else
		c = 'A';
	printf("%c%u", c, sym->id);
}

static void
emitconst(Node *np)
{
	Symbol *sym = np->sym;
	Type *tp = np->type;
	TUINT u;

	switch (tp->op) {
	case PTR:
	case INT:
	case ENUM:
		u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
		printf("#%c%llX",
		       np->type->letter,
		       (long long) sym->u.i & ones(tp->size));
		break;
	default:
		abort();
	}
}

static void
emitsym(unsigned op, void *arg)
{
	Node *np = arg;

	if ((np->sym->flags & SINITLST) == 0) {
		/*
		 * When we have a compound literal we are going
		 * to call to emitnode for every element of it,
		 * and it means that we will have two '\t'
		 * for the first element
		 */
		putchar('\t');
	}
	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
}

static void
emitletter(Type *tp)
{
	putchar(tp->letter);
	switch (tp->op) {
	case ARY:
	case STRUCT:
	case UNION:
		printf("%u", tp->id);
	}
}

static void
emittype(unsigned op, void *arg)
{
	TINT n;
	Symbol **sp;
	char *tag;
	Type *tp = arg;

	if (!(tp->prop & TDEFINED))
		return;

	switch (tp->op) {
	case ARY:
		emitletter(tp);
		putchar('\t');
		emitletter(tp->type);
		printf("\t#%c%llX\n",
		       sizettype->letter, (long long) tp->n.elem);
		return;
	case UNION:
	case STRUCT:
		emitletter(tp);
		tag = tp->tag->name;
		printf("\t\"%s\t#%c%lX\t#%c%X\n",
		       (tag) ? tag : "",
		       sizettype->letter,
		       tp->size,
		       sizettype->letter,
		       tp->align);
		n = tp->n.elem;
		for (sp = tp->p.fields; n-- > 0; ++sp)
			emit(ODECL, *sp);
		break;
	case PTR:
	case FTN:
		return;
	default:
		abort();
	}
}

static void
emitstring(Symbol *sym, Type *tp)
{
	char *bp, *s, *lim;
	int n;

	bp = sym->u.s;
	lim = &sym->u.s[tp->n.elem];
	while (bp < lim) {<commit_msg>[cc1] Admits enum in emittype()<commit_after>/* See LICENSE file for copyright and license details. */
static char sccsid[] = "@(#) ./cc1/code.c";
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "../inc/cc.h"
#include "cc1.h"

static void emitbin(unsigned, void *),
            emitcast(unsigned, void *),
            emitsym(unsigned, void *),
            emitexp(unsigned, void *),
            emitsymid(unsigned, void *),
            emittext(unsigned, void *),
            emitfun(unsigned, void *),
            emitdcl(unsigned, void *),
            emitinit(unsigned, void *),
            emittype(unsigned, void *);

char *optxt[] = {
	[OADD] = "+",
	[OSUB] = "-",
	[OMUL] = "*",
	[OINC] = ":i",
	[ODEC] =  ":d",
	[OPTR] = "@",
	[OMOD] = "%",
	[ODIV] = "/",
	[OSHL] = "l",
	[OSHR]  = "r",
	[OLT] = "<",
	[OGT] = ">",
	[OGE] = "]",
	[OLE] =  "[",
	[OEQ] = "=",
	[ONE] = "!",
	[OBAND] = "&",
	[OBXOR]  = "^",
	[OBOR] = "|",
	[OASSIGN] = ":",
	[OA_MUL] = ":*",
	[OA_DIV] = ":/",
	[OA_MOD] = ":%",
	[OA_ADD] = ":+",
	[OA_SUB] = ":-",
	[OA_SHL] = ":l",
	[OA_SHR] = ":r",
	[OA_AND] = ":&",
	[OA_XOR] = ":^",
	[OA_OR] = ":|",
	[OADDR] = "'",
	[OSNEG] = "_",
	[ONEG] = "n",
	[OCPL] = "~",
	[OAND] = "a",
	[OOR] = "o",
	[OASK] = "?",
	[OCOMMA] = ",",
	[OLABEL] = "L%d\n",
	[ODEFAULT] = "\tf\tL%d\n",
	[OBSWITCH] = "\ts",
	[OESWITCH] = "\tt\tL%d\n",
	[OCASE] = "\tv\tL%d",
	[OJUMP] = "\tj\tL%d\n",
	[OBRANCH] = "\ty\tL%d",
	[OEFUN] = "}\n",
	[OELOOP] = "\tb\n",
	[OBLOOP] = "\te\n",
	[ORET] = "\th",
	[OPAR] = "p",
	[OCALL] = "c",
	[OFIELD] = "."
};

void (*opcode[])(unsigned, void *) = {
	[OADD] = emitbin,
	[OSUB] = emitbin,
	[OMUL] = emitbin,
	[OINC] = emitbin,
	[ODEC] =  emitbin,
	[OPTR] = emitbin,
	[OMOD] = emitbin,
	[ODIV] = emitbin,
	[OSHL] = emitbin,
	[OSHR]  = emitbin,
	[OLT] = emitbin,
	[OGT] = emitbin,
	[OGE] = emitbin,
	[OLE] =  emitbin,
	[OEQ] = emitbin,
	[ONE] = emitbin,
	[OBAND] = emitbin,
	[OBXOR]  = emitbin,
	[OBOR] = emitbin,
	[OASSIGN] = emitbin,
	[OA_MUL] = emitbin,
	[OA_DIV] = emitbin,
	[OA_MOD] = emitbin,
	[OA_ADD] = emitbin,
	[OA_SUB] = emitbin,
	[OA_SHL] = emitbin,
	[OA_SHR] = emitbin,
	[OA_AND] = emitbin,
	[OA_XOR] = emitbin,
	[OA_OR] = emitbin,
	[OADDR] = emitbin,
	[OSNEG] = emitbin,
	[ONEG] = emitbin,
	[OCPL] = emitbin,
	[OAND] = emitbin,
	[OOR] = emitbin,
	[OCOMMA] = emitbin,
	[OCAST] = emitcast,
	[OSYM] = emitsym,
	[OASK] = emitbin,
	[OCOLON] = emitbin,
	[OFIELD]= emitbin,
	[OEXPR] = emitexp,
	[OLABEL] = emitsymid,
	[ODEFAULT] = emitsymid,
	[OCASE] = emitsymid,
	[OJUMP] = emitsymid,
	[OBRANCH] = emitsymid,
	[OEFUN] = emittext,
	[OELOOP] = emittext,
	[OBLOOP] = emittext,
	[OFUN] = emitfun,
	[ORET] = emittext,
	[ODECL] = emitdcl,
	[OBSWITCH] = emittext,
	[OESWITCH] = emitsymid,
	[OPAR] = emitbin,
	[OCALL] = emitbin,
	[OINIT] = emitinit,
	[OTYP] = emittype,
};

void
freetree(Node *np)
{
	if (!np)
		return;
	freetree(np->left);
	freetree(np->right);
	free(np);
}

static void
emitnode(Node *np)
{
	if (np)
		(*opcode[np->op])(np->op, np);
}

void
emit(unsigned op, void *arg)
{
	extern int failure;

	if (failure)
		return;
	(*opcode[op])(op, arg);
}

static void
emitvar(Symbol *sym)
{
	char c;
	short flags = sym->flags;

	if (flags & SLOCAL)
		c = 'T';
	else if (flags & SPRIVATE)
		c =  'Y';
	else if (flags & SGLOBAL)
		c = 'G';
	else if (flags & SREGISTER)
		c = 'R';
	else if (flags & SFIELD)
		c = 'M';
	else if (flags & SEXTERN)
		c = 'X';
	else
		c = 'A';
	printf("%c%u", c, sym->id);
}

static void
emitconst(Node *np)
{
	Symbol *sym = np->sym;
	Type *tp = np->type;
	TUINT u;

	switch (tp->op) {
	case PTR:
	case INT:
	case ENUM:
		u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
		printf("#%c%llX",
		       np->type->letter,
		       (long long) sym->u.i & ones(tp->size));
		break;
	default:
		abort();
	}
}

static void
emitsym(unsigned op, void *arg)
{
	Node *np = arg;

	if ((np->sym->flags & SINITLST) == 0) {
		/*
		 * When we have a compound literal we are going
		 * to call to emitnode for every element of it,
		 * and it means that we will have two '\t'
		 * for the first element
		 */
		putchar('\t');
	}
	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
}

static void
emitletter(Type *tp)
{
	putchar(tp->letter);
	switch (tp->op) {
	case ARY:
	case STRUCT:
	case UNION:
		printf("%u", tp->id);
	}
}

static void
emittype(unsigned op, void *arg)
{
	TINT n;
	Symbol **sp;
	char *tag;
	Type *tp = arg;

	if (!(tp->prop & TDEFINED))
		return;

	switch (tp->op) {
	case ARY:
		emitletter(tp);
		putchar('\t');
		emitletter(tp->type);
		printf("\t#%c%llX\n",
		       sizettype->letter, (long long) tp->n.elem);
		return;
	case UNION:
	case STRUCT:
		emitletter(tp);
		tag = tp->tag->name;
		printf("\t\"%s\t#%c%lX\t#%c%X\n",
		       (tag) ? tag : "",
		       sizettype->letter,
		       tp->size,
		       sizettype->letter,
		       tp->align);
		n = tp->n.elem;
		for (sp = tp->p.fields; n-- > 0; ++sp)
			emit(ODECL, *sp);
		break;
	case PTR:
	case FTN:
	case ENUM:
		return;
	default:
		abort();
	}
}

static void
emitstring(Symbol *sym, Type *tp)
{
	char *bp, *s, *lim;
	int n;

	bp = sym->u.s;
	lim = &sym->u.s[tp->n.elem];
	while (bp < lim) {
{'fraction_non_alphanumeric': 0.23251985279876042, 'fraction_numerical': 0.0008715862870424172, 'mean_word_length': 2.959739263803681, 'pattern_counts': {'":': 26, '<': 15, '<?xml version=': 0, '>': 93, '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': '7334518', 'n_tokens_mistral': 5148, 'n_tokens_neox': 4959, 'n_words': 1022}