<commit_before>/* See LICENSE file for copyright and license details. */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)

Node *expr(void);

int
cmpnode(Node *np, TUINT val)
{
	Symbol *sym;
	Type *tp;
	TUINT mask, nodeval;

	if (!np || !(np->flags & NCONST) || !np->sym)
		return 0;
	sym = np->sym;
	tp = sym->type;

	switch (tp->op) {
	case PTR:
	case INT:
		mask = (val > 1) ? ones(np->type->size) : -1;
		nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
		return (nodeval & mask) == (val & mask);
	case FLOAT:
		return sym->u.f == val;
	}
	return 0;
}

static Node *
promote(Node *np)
{
	Type *tp;
	Node *new;
	struct limits *lim, *ilim;

	tp = np->type;

	switch (tp->op) {
	case ENUM:
	case INT:
		if (tp->n.rank >= inttype->n.rank)
			return np;
		lim = getlimits(tp);
		ilim = getlimits(inttype);
		tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
		break;
	case FLOAT:
		/* TODO: Add support for C99 float math */
		tp = doubletype;
		break;
	default:
		abort();
	}
	if ((new = convert(np, tp, 1)) != NULL)
		return new;
	return np;
}

static void
arithconv(Node **p1, Node **p2)
{
	int to = 0, s1, s2;
	unsigned r1, r2;
	Type *tp1, *tp2;
	Node *np1, *np2;
	struct limits *lp1, *lp2;

	np1 = promote(*p1);
	np2 = promote(*p2);

	tp1 = np1->type;
	tp2 = np2->type;

	if (tp1 == tp2)
		goto set_p1_p2;

	s1 = (tp1->prop & TSIGNED) != 0;
	r1 = tp1->n.rank;
	lp1 = getlimits(tp1);

	s2 = (tp2->prop & TSIGNED) != 0;
	r2 = tp2->n.rank;
	lp2 = getlimits(tp2);

	if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
		to = r1 - r2;
	} else if (!s1) {
		if (r1 >= r2 || lp1->max.i >= lp2->max.i)
			to = 1;
		else
			to = -1;
	} else {
		if (r2 >= r1 || lp2->max.i >= lp1->max.i)
			to = -1;
		else
			to = 1;
	}

	if (to > 0)
		np2 = convert(np2, tp1, 1);
	else if (to < 0)
		np1 = convert(np1, tp2, 1);
		
set_p1_p2:
	*p1 = np1;
	*p2 = np2;
}

static int
null(Node *np)
{
	if (!np->flags & NCONST || np->type != pvoidtype)
		return 0;
	return cmpnode(np, 0);
}

static Node *
chkternary(Node *yes, Node *no)
{
	/*
	 * FIXME:
	 * We are ignoring type qualifiers here,
	 * but the standard has strong rules about this.
	 * take a look to 6.5.15
	 */

	if (!eqtype(yes->type, no->type, 1)) {
		if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
			arithconv(&yes, &no);
		} else if (yes->type->op != PTR && no->type->op != PTR) {
			goto wrong_type;
		} else {
			/* convert integer 0 to NULL */
			if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
				yes = convert(yes, pvoidtype, 0);
			if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
				no = convert(no, pvoidtype, 0);
			/*
			 * At this point the type of both should be
			 * a pointer to something, or we have don't
			 * compatible types
			 */
			if (yes->type->op != PTR || no->type->op != PTR)
				goto wrong_type;
			/*
			 * If we have a null pointer constant then
			 * convert to the another type
			 */
			if (null(yes))
				yes = convert(yes, no->type, 0);
			if (null(no))
				no = convert(no, yes->type, 0);

			if (!eqtype(yes->type, no->type, 1))
				goto wrong_type;
		}
	}
	return node(OCOLON, yes->type, yes, no);

wrong_type:
	errorp("type mismatch in conditional expression");
	freetree(yes);
	freetree(no);
	return constnode(zero);
}

static void
chklvalue(Node *np)
{
	if (!(np->flags & NLVAL))
		errorp("lvalue required in operation");
	if (np->type == voidtype)
		errorp("invalid use of void expression");
}

Node *
decay(Node *np)
{
	Node *new;
	Type *tp = np->type;

	switch (tp->op) {
	case ARY:
		tp = tp->type;
		if (np->op == OPTR) {
			new = np->left;
			free(np);
			new->type = mktype(tp, PTR, 0, NULL);
			return new;
		}
	case FTN:
		new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
		if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
			new->flags |= NCONST;
		return new;
	default:
		return np;
	}
}

static Node *
integerop(char op, Node *lp, Node *rp)
{
	if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
		error("operator requires integer operands");
	arithconv(&lp, &rp);
	return simplify(op, lp->type, lp, rp);
}

static Node *
integeruop(char op, Node *np)
{
	if (!(np->type->prop & TINTEGER))
		error("unary operator requires integer operand");
	np = promote(np);
	if (op == OCPL && np->op == OCPL)
		return np->left;
	return simplify(op, np->type, np, NULL);
}

static Node *
numericaluop(char op, Node *np)
{
	if (!(np->type->prop & TARITH))
		error("unary operator requires numerical operand");
	np = promote(np);
	if (op == OSNEG && np->op == OSNEG)
		return np->left;
	if (op == OADD)
		return np;
	return simplify(op, np->type, np, NULL);
}

Node *
convert(Node *np, Type *newtp, char iscast)
{
	Type *oldtp = np->type;

	if (eqtype(newtp, oldtp, 0))
		return np;

	switch (oldtp->op) {
	case ENUM:
	case INT:
	case FLOAT:
		switch (newtp->op) {
		case PTR:
			if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
				return NULL;
			/* PASSTHROUGH */
		case INT:
		case FLOAT:
		case ENUM:
			break;
		default:
			return NULL;
		}
		break;
	case PTR:
		switch (newtp->op) {
		case ENUM:
		case INT:
		case VOID:
			if (!iscast)
				return NULL;
			break;
		case PTR:
			if (eqtype(newtp, oldtp, 1) ||
			    iscast ||
			    newtp == pvoidtype || oldtp == pvoidtype) {
				np->type = newtp;
				return np;
			}
		default:
			return NULL;
		}
	default:
		return NULL;
	}
	return castcode(np, newtp);
}

static Node *
parithmetic(char op, Node *lp, Node *rp)
{
	Type *tp;
	Node *size, *np;

	if (lp->type->op != PTR)
		XCHG(lp, rp, np);

	tp = rp->type;
	if (tp->op == PTR && !(tp->type->prop & TDEFINED))
		goto incomplete;
	tp = lp->type;
	if (!(tp->type->prop & TDEFINED))
		goto incomplete;
	size = sizeofnode(tp->type);

	if (op == OSUB && BTYPE(rp) == PTR) {
		if (tp != rp->type)
			goto incorrect;
		lp = node(OSUB, pdifftype, lp, rp);
		return node(ODIV, inttype, lp, size);
	}
	if (!(rp->type->prop & TINTEGER))
		goto incorrect;

	rp = convert(promote(rp), sizettype, 0);
	rp = simplify(OMUL, sizettype, rp, size);
	rp = convert(rp, tp, 1);

	return simplify(op, tp, lp, rp);

incomplete:
	errorp("invalid use of undefined type");
	return lp;
incorrect:
	errorp("incorrect arithmetic operands");
	return lp;<commit_msg>[cc1] Calls to eqtype() in parithmetic()<commit_after>/* See LICENSE file for copyright and license details. */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)

Node *expr(void);

int
cmpnode(Node *np, TUINT val)
{
	Symbol *sym;
	Type *tp;
	TUINT mask, nodeval;

	if (!np || !(np->flags & NCONST) || !np->sym)
		return 0;
	sym = np->sym;
	tp = sym->type;

	switch (tp->op) {
	case PTR:
	case INT:
		mask = (val > 1) ? ones(np->type->size) : -1;
		nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
		return (nodeval & mask) == (val & mask);
	case FLOAT:
		return sym->u.f == val;
	}
	return 0;
}

static Node *
promote(Node *np)
{
	Type *tp;
	Node *new;
	struct limits *lim, *ilim;

	tp = np->type;

	switch (tp->op) {
	case ENUM:
	case INT:
		if (tp->n.rank >= inttype->n.rank)
			return np;
		lim = getlimits(tp);
		ilim = getlimits(inttype);
		tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
		break;
	case FLOAT:
		/* TODO: Add support for C99 float math */
		tp = doubletype;
		break;
	default:
		abort();
	}
	if ((new = convert(np, tp, 1)) != NULL)
		return new;
	return np;
}

static void
arithconv(Node **p1, Node **p2)
{
	int to = 0, s1, s2;
	unsigned r1, r2;
	Type *tp1, *tp2;
	Node *np1, *np2;
	struct limits *lp1, *lp2;

	np1 = promote(*p1);
	np2 = promote(*p2);

	tp1 = np1->type;
	tp2 = np2->type;

	if (tp1 == tp2)
		goto set_p1_p2;

	s1 = (tp1->prop & TSIGNED) != 0;
	r1 = tp1->n.rank;
	lp1 = getlimits(tp1);

	s2 = (tp2->prop & TSIGNED) != 0;
	r2 = tp2->n.rank;
	lp2 = getlimits(tp2);

	if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
		to = r1 - r2;
	} else if (!s1) {
		if (r1 >= r2 || lp1->max.i >= lp2->max.i)
			to = 1;
		else
			to = -1;
	} else {
		if (r2 >= r1 || lp2->max.i >= lp1->max.i)
			to = -1;
		else
			to = 1;
	}

	if (to > 0)
		np2 = convert(np2, tp1, 1);
	else if (to < 0)
		np1 = convert(np1, tp2, 1);
		
set_p1_p2:
	*p1 = np1;
	*p2 = np2;
}

static int
null(Node *np)
{
	if (!np->flags & NCONST || np->type != pvoidtype)
		return 0;
	return cmpnode(np, 0);
}

static Node *
chkternary(Node *yes, Node *no)
{
	/*
	 * FIXME:
	 * We are ignoring type qualifiers here,
	 * but the standard has strong rules about this.
	 * take a look to 6.5.15
	 */

	if (!eqtype(yes->type, no->type, 1)) {
		if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
			arithconv(&yes, &no);
		} else if (yes->type->op != PTR && no->type->op != PTR) {
			goto wrong_type;
		} else {
			/* convert integer 0 to NULL */
			if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
				yes = convert(yes, pvoidtype, 0);
			if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
				no = convert(no, pvoidtype, 0);
			/*
			 * At this point the type of both should be
			 * a pointer to something, or we have don't
			 * compatible types
			 */
			if (yes->type->op != PTR || no->type->op != PTR)
				goto wrong_type;
			/*
			 * If we have a null pointer constant then
			 * convert to the another type
			 */
			if (null(yes))
				yes = convert(yes, no->type, 0);
			if (null(no))
				no = convert(no, yes->type, 0);

			if (!eqtype(yes->type, no->type, 1))
				goto wrong_type;
		}
	}
	return node(OCOLON, yes->type, yes, no);

wrong_type:
	errorp("type mismatch in conditional expression");
	freetree(yes);
	freetree(no);
	return constnode(zero);
}

static void
chklvalue(Node *np)
{
	if (!(np->flags & NLVAL))
		errorp("lvalue required in operation");
	if (np->type == voidtype)
		errorp("invalid use of void expression");
}

Node *
decay(Node *np)
{
	Node *new;
	Type *tp = np->type;

	switch (tp->op) {
	case ARY:
		tp = tp->type;
		if (np->op == OPTR) {
			new = np->left;
			free(np);
			new->type = mktype(tp, PTR, 0, NULL);
			return new;
		}
	case FTN:
		new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
		if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
			new->flags |= NCONST;
		return new;
	default:
		return np;
	}
}

static Node *
integerop(char op, Node *lp, Node *rp)
{
	if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
		error("operator requires integer operands");
	arithconv(&lp, &rp);
	return simplify(op, lp->type, lp, rp);
}

static Node *
integeruop(char op, Node *np)
{
	if (!(np->type->prop & TINTEGER))
		error("unary operator requires integer operand");
	np = promote(np);
	if (op == OCPL && np->op == OCPL)
		return np->left;
	return simplify(op, np->type, np, NULL);
}

static Node *
numericaluop(char op, Node *np)
{
	if (!(np->type->prop & TARITH))
		error("unary operator requires numerical operand");
	np = promote(np);
	if (op == OSNEG && np->op == OSNEG)
		return np->left;
	if (op == OADD)
		return np;
	return simplify(op, np->type, np, NULL);
}

Node *
convert(Node *np, Type *newtp, char iscast)
{
	Type *oldtp = np->type;

	if (eqtype(newtp, oldtp, 0))
		return np;

	switch (oldtp->op) {
	case ENUM:
	case INT:
	case FLOAT:
		switch (newtp->op) {
		case PTR:
			if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
				return NULL;
			/* PASSTHROUGH */
		case INT:
		case FLOAT:
		case ENUM:
			break;
		default:
			return NULL;
		}
		break;
	case PTR:
		switch (newtp->op) {
		case ENUM:
		case INT:
		case VOID:
			if (!iscast)
				return NULL;
			break;
		case PTR:
			if (eqtype(newtp, oldtp, 1) ||
			    iscast ||
			    newtp == pvoidtype || oldtp == pvoidtype) {
				np->type = newtp;
				return np;
			}
		default:
			return NULL;
		}
	default:
		return NULL;
	}
	return castcode(np, newtp);
}

static Node *
parithmetic(char op, Node *lp, Node *rp)
{
	Type *tp;
	Node *size, *np;

	if (lp->type->op != PTR)
		XCHG(lp, rp, np);

	tp = rp->type;
	if (tp->op == PTR && !(tp->type->prop & TDEFINED))
		goto incomplete;
	tp = lp->type;
	if (!(tp->type->prop & TDEFINED))
		goto incomplete;
	size = sizeofnode(tp->type);

	if (op == OSUB && BTYPE(rp) == PTR) {
		if (!eqtype(tp, rp->type, 0))
			goto incorrect;
		lp = node(OSUB, pdifftype, lp, rp);
		return node(ODIV, inttype, lp, size);
	}
	if (!(rp->type->prop & TINTEGER))
		goto incorrect;

	rp = convert(promote(rp), sizettype, 0);
	rp = simplify(OMUL, sizettype, rp, size);
	rp = convert(rp, tp, 1);

	return simplify(op, tp, lp, rp);

incomplete:
	errorp("invalid use of undefined type");
	return lp;
incorrect:
	errorp("incorrect arithmetic operands");
	return lp;
{'fraction_non_alphanumeric': 0.1855968688845401, 'fraction_numerical': 0.01643835616438356, 'mean_word_length': 3.0176100628930818, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 225, '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': '2694985', 'n_tokens_mistral': 5879, 'n_tokens_neox': 5366, 'n_words': 1489}