#ifndef EJIT_COMMON_H
#define EJIT_COMMON_H

#include <stdbool.h>
#include "vec.h"

enum ejit_opcode {
	MOVI,
	MOVR,
	MOVR_F,

	LDI8,
	LDI16,
	LDI32,
	LDI64,
	LDIU8,
	LDIU16,
	LDIU32,
	LDIU64,
	LDIF,
	LDID,

	LDXI8,
	LDXI16,
	LDXI32,
	LDXI64,
	LDXIU8,
	LDXIU16,
	LDXIU32,
	LDXIU64,
	LDXIF,
	LDXID,

	STI8,
	STI16,
	STI32,
	STI64,
	STIU8,
	STIU16,
	STIU32,
	STIU64,
	STIF,
	STID,

	STXI8,
	STXI16,
	STXI32,
	STXI64,
	STXIU8,
	STXIU16,
	STXIU32,
	STXIU64,
	STXIF,
	STXID,

	ADDR,
	ADDR_F,
	SUBR,
	SUBR_F,
	MULR,
	DIVR,
	NEGR,

	EQR,
	LTR,

	BLTR,
	BNEI,
	BEQI,
	JMP,

	PARAM,
	PARAM_F,

	ARG,
	ARG_I,
	ARG_F,
	ARG_FI,

	ESCAPEI,
	ESCAPEI_F,

	CALLI,
	CALLI_F,

	RET,
	RET_I,
	RET_F,
	RET_FI,

	RETVAL,
	RETVAL_F,

	START,
	END,
	LABEL,

	OPCODE_COUNT,
};

struct ejit_insn {
	union {
		enum ejit_opcode op;
		void *addr;
	};

	size_t r0;
	size_t r1;
	union {
		size_t r2;
		void *p;
		long o;
		double d;
	};
};

struct ejit_func {
	struct vec insns;
	enum ejit_type rtype;

	size_t gpr;
	size_t fpr;

	void *arena;
	size_t size;
};


union interp_ret {
	long r;
	double d;
};

union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], bool run, void ***labels_wb);

bool ejit_compile(struct ejit_func *f);

#endif /* EJIT_COMMON_H */