/*
 * Instruction selector Monoburg specification for IA-32.
 *
 * Copyright (C) 2006  Pekka Enberg
 *
 * This file is released under the GPL version 2. Please refer to the file
 * LICENSE for details.
 */

#include <jit/basic-block.h>
#include <jit/compilation-unit.h>
#include <jit/compiler.h>
#include <jit/expression.h>
#include <jit/statement.h>

#include <arch/instruction.h>
#include <arch/stack-frame.h>

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

#define MBCGEN_TYPE struct basic_block
#define MBCOST_DATA struct basic_block
#define MBTREE_TYPE struct tree_node
#define MBTREE_OP(t) tree_op(t)
#define MBTREE_LEFT(t) tree->kids[0]
#define MBTREE_RIGHT(t) tree->kids[1]
#define MBREG_TYPE struct var_info *

#define MBMAX_OPCODES STMT_LAST

#define MONOBURG_LOG 1
#define HAVE_ARRAY_ELEM_INIT 1

%%

%termprefix EXPR_ OP_ STMT_

%start stmt

reg:	EXPR_VALUE	0
{
}

reg:	EXPR_LOCAL	1
{
}

reg:   EXPR_VAR
{
}

reg:	OP_ADD(reg, EXPR_LOCAL) 1
{
}

reg:	OP_ADD(reg, EXPR_VALUE) 1
{
}

reg:	OP_SUB(reg, EXPR_LOCAL) 1
{
}

reg:	OP_MUL(reg, EXPR_LOCAL) 1
{
}

reg:	OP_DIV(reg, EXPR_LOCAL) 1
{
}

reg:	OP_REM(reg, EXPR_LOCAL) 1
{
}

reg:	OP_NEG(reg) 1
{
}

reg:	OP_SHL(reg, EXPR_LOCAL) 1
{
}

reg:	OP_SHR(reg, EXPR_LOCAL) 1
{
}

reg:	OP_USHR(reg, EXPR_LOCAL) 1
{
}

reg:	OP_OR(reg, EXPR_LOCAL) 1
{
}

reg:	OP_AND(reg, EXPR_LOCAL) 1
{
}

reg:	OP_XOR(reg, EXPR_LOCAL) 1
{
}

reg:	EXPR_INVOKE(arg) 1
{
}

reg:	EXPR_INVOKEVIRTUAL(arg) 1
{
}

reg:	OP_EQ(reg, EXPR_LOCAL) 1
{
}

reg:	OP_EQ(reg, EXPR_VALUE) 1
{
}

reg:	OP_NE(reg, EXPR_LOCAL) 1
{
}

reg:	OP_NE(reg, EXPR_VALUE) 1
{
}

reg:	EXPR_CLASS_FIELD 1
{
}

reg:	EXPR_INSTANCE_FIELD(reg) 1
{
}

reg:	EXPR_NEW
{
}

reg:	EXPR_NEWARRAY(reg)
{
}

arg:	EXPR_NO_ARGS
{
}

arg:	EXPR_ARG(EXPR_VALUE)
{
}

arg:	EXPR_ARG(reg)
{
}

arg:	EXPR_ARGS_LIST(arg, arg)
{
}

stmt:	STMT_RETURN(reg)
{
}

stmt:	STMT_VOID_RETURN
{
}

stmt:	STMT_EXPRESSION(reg)
{
}

stmt:	STMT_STORE(EXPR_CLASS_FIELD, EXPR_VALUE)
{
}

inst_field: EXPR_INSTANCE_FIELD(reg) 1
{
}

stmt:	STMT_STORE(inst_field, reg)
{
}

stmt:	STMT_STORE(EXPR_LOCAL, reg)
{
}

stmt:  STMT_STORE(EXPR_VAR, reg)
{
}

stmt:	STMT_IF(reg)
{
}

%%

static void emit_code(struct basic_block *bb, MBState *state, int goal)
{
	MBState *kids[2];
	int ern;
	const guint16 *nts;
	int i;

	ern = mono_burg_rule(state, goal);
	nts = mono_burg_nts_data + mono_burg_nts[ern];
	mono_burg_kids(state, ern, kids);

	for (i = 0; nts[i]; i++) 
		emit_code(bb, kids[i], nts[i]);

	mono_burg_emit(ern, state, state->tree, bb);
}

static void free_state(MBState *state)
{
	if (!state)
		return;

	free_state(state->left);
	free_state(state->right);

	g_free(state);
}

static void insn_select(struct basic_block *bb)
{
	struct statement *stmt;
	MBState *state;

	mono_burg_init();

	for_each_stmt(stmt, &bb->stmt_list) {
		state = mono_burg_label(&stmt->node, bb);
		emit_code(bb, state, MB_NTERM_stmt);
		free_state(state);
	}
}

int select_instructions(struct compilation_unit *cu)
{
	struct basic_block *bb;

	for_each_basic_block(bb, &cu->bb_list)
		insn_select(bb);

	return 0;
}
