/* $Id: declaration.h,v 1.72 2009/01/27 15:40:22 potyra Exp $ 
 *
 * Copyright (C) 2007-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#ifndef __DECLARATION_H_INCLUDED
#define __DECLARATION_H_INCLUDED

#include <inttypes.h>

#include "type.h"

/*
 * Constants
 */
#define DECL_CLASS_NONE		0
#define DECL_CLASS_COUNT	32
#define DECL_REG_COUNT		(DECL_CLASS_COUNT * 8)
#define DECL_MEMORY		DECL_REG_COUNT

/*
 * Types
 */
struct storage_register {
	const char *name;
	unsigned int class;
	enum type_type type;
};

struct decl_live {
	struct decl_live *prev;
	struct decl_live *next;
	struct declaration *decl;
};

struct declaration {
	struct declaration *prev;
	struct declaration *next;

	const char *identifier;
	enum type_storage {
		STORAGE_NONE = 0,
		STORAGE_AUTO,
		STORAGE_STATIC,
		STORAGE_TYPEDEF,
		STORAGE_REGISTER,
		STORAGE_EXTERN,
		STORAGE_PARAM,
		STORAGE_ASM,
	} storage;
	unsigned int mod_inline;
	unsigned int attr_aligned;
	unsigned int attr_noreturn;
	struct expr *nbits;
	struct expr *initializer;
	struct stmt *stmt;
	struct type *type_name;
	const char *regname;
	const char *code;

	struct declaration *clone;

	/* SSA Info */
	struct expr *assign_expr;
	unsigned int acount;
	unsigned int wcount;
	unsigned int rcount;

	/* Register Allocation */
	unsigned int storage_class;
	int storage_mem;
	unsigned int spills;
	unsigned int reg_count[DECL_CLASS_COUNT];
	struct decl_live *move_first;
	struct decl_live *move_last;
	struct decl_live *conflict_first;
	struct decl_live *conflict_last;
	struct decl_live *conflict_save_first;
	struct decl_live *conflict_save_last;
	unsigned int storage_register;

	unsigned int offset;

	/* FAUjitcc */
	int jit;
};

/*
 * Functions
 */
extern void
declaration_rename_structunionenum(
	struct declaration *dion,
	enum type_type type,
	const char *old,
	const char *new
);

extern void
declaration_rename_type(
	struct declaration *dion,
	const char *old,
	const char *new);

extern struct declaration *
declaration_new(void);

extern void
declaration_name_set(struct declaration *d, const char *name);
extern const char *
declaration_name_get(struct declaration *dor);
extern void
declaration_type_get(struct type **adp, struct declaration *dor);
extern void
declaration_initializer_set(struct declaration *dor, struct expr *initializer);
extern struct expr *
declaration_initializer_get(struct declaration *dor);

extern struct declaration *
declaration_identifier(const char *name);

extern void
declaration_free(struct declaration *dor);

extern void
declaration_alive(struct storage_register *reginfo,
		unsigned int *classinfo, unsigned int *typeinfo,
		struct stmt *fs);

#endif /* __DECLARATION_H_INCLUDED */
