Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
8e0086df
Commit
8e0086df
authored
Mar 14, 2005
by
Sebastian Hack
Browse files
Added be arch reflection/backend support infrastructure.
parent
1a417753
Changes
10
Hide whitespace changes
Inline
Side-by-side
ir/be/Makefile.in
View file @
8e0086df
...
...
@@ -23,7 +23,7 @@ SOURCES += Makefile.in besched.h belistsched.h belistsched.c \
beutil.h bemain.c besched.c bemain.c belive.c belive.h benumb.h
\
benumb_t.h benumb.c bechordal.c bera.c beutil.c phistat.c
\
bephiopt.c bephicoal.c bera.h bechordalspill.c
\
beasm_dump_globals.c beasm_asm_gnu.c
beasm_dump_globals.c beasm_asm_gnu.c
bearch.h bearch.c
include
$(topdir)/MakeRules
...
...
ir/be/bearch.c
0 → 100644
View file @
8e0086df
/**
* Processor architecture specification.
* @author Sebastian Hack
* @date 11.2.2005
*
* $Id$
*/
#include "bearch_t.h"
#include "firm_config.h"
#include "set.h"
#include "entity.h"
#include "ircons_t.h"
#if 1
/* HAVE_ALLOCA_H */
#include <alloca.h>
#endif
/* HAVE_ALLOCA_H */
#define INIT_HEADER(tgt, kind_suffix, a_isa, str) \
do { \
arch_header_t *h = (arch_header_t *) (tgt); \
memset(tgt, 0, sizeof(*(tgt))); \
h->kind = arch_kind_ ## kind_suffix; \
h->name = new_id_from_str(str); \
h->isa = a_isa; \
} while(0)
static
INLINE
int
hash_header
(
const
arch_header_t
*
header
)
{
int
res
=
HASH_PTR
(
header
->
isa
);
res
=
37
*
res
+
HASH_STR
(
header
->
name
,
strlen
(
header
->
name
));
res
=
37
*
res
+
header
->
kind
;
return
res
;
}
static
int
cmp_header
(
const
void
*
a
,
const
void
*
b
,
size_t
size
)
{
const
arch_header_t
*
h1
=
a
;
const
arch_header_t
*
h2
=
b
;
return
!
(
h1
->
kind
==
h2
->
kind
&&
strcmp
(
h1
->
name
,
h2
->
name
)
==
0
);
}
static
set
*
arch_data
=
NULL
;
static
set
*
get_arch_data
(
void
)
{
if
(
!
arch_data
)
arch_data
=
new_set
(
cmp_header
,
256
);
return
arch_data
;
}
typedef
struct
_obj_info_t
{
const
char
*
name
;
int
listed_in_isa
;
size_t
size
;
}
obj_info_t
;
static
const
obj_info_t
obj_info
[]
=
{
#define ARCH_OBJ(name,listed_in_isa) { #name, listed_in_isa, sizeof(arch_ ## name ## _t) },
#include "bearch_obj.def"
#undef ARCH_OBJ
{
0
}
};
/**
* Insert an arch object to the global arch obj storage.
*
* If the object has already been created there, nothing is done and
* the old object is created.
*
* @param kind The kind of the arch object.
* @param isa The isa the object belongs to or NULL if it is the isa
* itself.
* @param name The name of the object.
* @param was_new A pointer to an int where 1/0 is stored if the
* object was created or already present. If NULL, it is simply ignored.
* @return A pointer to the object.
*/
static
INLINE
void
*
_arch_data_insert
(
arch_kind_t
kind
,
arch_isa_t
*
isa
,
const
char
*
name
,
size_t
size
,
int
*
was_new
)
{
const
obj_info_t
*
info
=
&
obj_info
[
kind
];
arch_header_t
*
data
=
alloca
(
size
);
arch_header_t
*
res
=
NULL
;
memset
(
data
,
0
,
size
);
data
->
kind
=
kind
;
data
->
isa
=
isa
;
data
->
name
=
get_id_str
(
new_id_from_str
(
name
));
data
->
is_new
=
1
;
res
=
set_insert
(
get_arch_data
(),
data
,
size
,
hash_header
(
data
));
/* If the object is newly created and thus not yet present
* in the set, add it to the isa */
if
(
res
->
is_new
)
{
/*
* The inserted object was no isa, list it in the isa if this is
* desired.
*/
if
(
isa
&&
info
->
listed_in_isa
)
list_add
(
&
res
->
list
,
&
isa
->
heads
[
kind
]);
/* The inserted object is an isa, so initialize all its list heads. */
else
{
int
i
;
arch_isa_t
*
isa
=
(
arch_isa_t
*
)
res
;
for
(
i
=
0
;
i
<
arch_kind_last
;
++
i
)
INIT_LIST_HEAD
(
&
isa
->
heads
[
i
]);
}
}
/*
* If the caller wants to know, of the object was newly created,
* give it to him.
*/
if
(
was_new
)
*
was_new
=
res
->
is_new
;
/* Mark the object as NOT new. */
res
->
is_new
=
0
;
return
res
;
}
#define arch_data_insert(type_suffix, isa, name, was_new) \
_arch_data_insert(arch_kind_ ## type_suffix, isa, name, sizeof(arch_ ## type_suffix ## _t), was_new)
static
INLINE
void
*
_arch_data_find
(
arch_kind_t
kind
,
const
arch_isa_t
*
isa
,
const
char
*
name
)
{
arch_header_t
header
;
memset
(
&
header
,
0
,
sizeof
(
header
));
header
.
kind
=
kind
;
header
.
isa
=
(
arch_isa_t
*
)
isa
;
header
.
name
=
name
;
return
set_find
(
get_arch_data
(),
&
header
,
sizeof
(
header
),
hash_header
(
&
header
));
}
#define arch_data_find(type_suffix, isa, name) \
_arch_data_find(arch_kind_ ## type_suffix, isa, name)
arch_isa_t
*
arch_add_isa
(
const
char
*
name
)
{
return
arch_data_insert
(
isa
,
NULL
,
name
,
NULL
);
}
arch_register_class_t
*
arch_add_register_class
(
arch_isa_t
*
isa
,
const
char
*
name
,
int
n_regs
)
{
arch_register_class_t
*
cls
=
_arch_data_insert
(
arch_kind_register_class
,
isa
,
name
,
sizeof
(
arch_register_class_t
)
+
n_regs
*
sizeof
(
arch_register_t
*
),
NULL
);
cls
->
n_regs
=
n_regs
;
return
cls
;
}
arch_register_t
*
arch_add_register
(
arch_register_class_t
*
cls
,
int
index
,
const
char
*
name
)
{
arch_register_t
*
reg
=
NULL
;
assert
(
index
>=
0
&&
index
<
cls
->
n_regs
);
reg
=
_arch_data_insert
(
arch_kind_register
,
arch_obj_get_isa
(
cls
),
name
,
sizeof
(
arch_register_t
),
NULL
);
cls
->
regs
[
index
]
=
reg
;
reg
->
index
=
index
;
reg
->
reg_class
=
cls
;
reg
->
flags
=
arch_register_flag_none
;
return
reg
;
}
arch_immediate_t
*
arch_add_immediate
(
arch_isa_t
*
isa
,
const
char
*
name
,
ir_mode
*
mode
)
{
arch_immediate_t
*
imm
=
arch_data_insert
(
immediate
,
isa
,
name
,
NULL
);
imm
->
mode
=
mode
;
return
imm
;
}
static
const
size_t
operand_sizes
[]
=
{
0
,
0
,
sizeof
(
entity
*
),
sizeof
(
arch_register_t
*
),
sizeof
(
tarval
*
)
};
arch_insn_format_t
*
arch_add_insn_format
(
arch_isa_t
*
isa
,
const
char
*
name
,
int
n_in
,
int
n_out
)
{
int
i
;
arch_insn_format_t
*
fmt
=
_arch_data_insert
(
arch_kind_insn_format
,
isa
,
name
,
sizeof
(
arch_insn_format_t
)
+
(
n_in
+
n_out
)
*
sizeof
(
arch_operand_type_t
),
NULL
);
fmt
->
n_in
=
n_in
;
fmt
->
n_out
=
n_out
;
fmt
->
irn_data_size
=
0
;
/*
* Compute the number of bytes which must be extra allocated if this
* opcode is instantiated.
*/
for
(
i
=
0
;
i
<
fmt
->
n_in
;
++
i
)
{
arch_operand_t
*
op
=
arch_get_in_operand
(
fmt
,
i
);
op
->
offset_in_irn_data
=
fmt
->
irn_data_size
;
fmt
->
irn_data_size
+=
operand_sizes
[
op
->
type
];
}
if
(
fmt
->
n_out
==
1
)
{
arch_operand_t
*
op
=
arch_get_in_operand
(
fmt
,
i
);
op
->
offset_in_irn_data
=
fmt
->
irn_data_size
;
fmt
->
irn_data_size
+=
operand_sizes
[
op
->
type
];
}
return
fmt
;
}
arch_insn_t
*
arch_add_insn
(
arch_insn_format_t
*
fmt
,
const
char
*
name
)
{
/* Insert the insn into the isa. */
arch_insn_t
*
insn
=
arch_data_insert
(
insn
,
arch_obj_get_isa
(
fmt
),
name
,
NULL
);
insn
->
format
=
fmt
;
insn
->
op
=
new_ir_op
(
get_next_ir_opcode
(),
name
,
op_pin_state_pinned
,
0
,
oparity_dynamic
,
0
,
sizeof
(
arch_irn_data_t
)
+
fmt
->
irn_data_size
);
return
insn
;
}
arch_insn_format_t
*
arch_find_insn_format
(
arch_isa_t
*
isa
,
const
char
*
name
)
{
return
arch_data_find
(
insn_format
,
isa
,
name
);
}
arch_isa_t
*
arch_find_isa
(
const
char
*
name
)
{
return
arch_data_find
(
isa
,
NULL
,
name
);
}
arch_register_class_t
*
arch_find_register_class_t
(
arch_isa_t
*
isa
,
const
char
*
name
)
{
return
arch_data_find
(
register_class
,
isa
,
name
);
}
arch_register_set_t
*
arch_get_register_set_for_class
(
arch_register_class_t
*
cls
)
{
return
_arch_get_register_set_for_class
(
cls
);
}
ir_node
*
arch_new_node
(
const
arch_insn_t
*
insn
,
ir_graph
*
irg
,
ir_node
*
block
,
ir_mode
*
mode
,
int
arity
,
ir_node
**
in
)
{
ir_node
*
irn
=
new_ir_node
(
NULL
,
irg
,
block
,
insn
->
op
,
mode
,
arity
,
in
);
arch_irn_data_t
*
data
=
(
void
*
)
&
irn
->
attr
;
data
->
magic
=
ARCH_IRN_FOURCC
;
data
->
insn
=
insn
;
return
irn
;
}
ir_node
*
arch_new_node_bare
(
const
arch_insn_t
*
insn
,
ir_graph
*
irg
,
int
arity
)
{
int
i
;
ir_node
**
in
=
alloca
(
sizeof
(
in
[
0
])
*
arity
);
for
(
i
=
0
;
i
<
arity
;
++
i
)
in
[
i
]
=
new_Unknown
(
mode_Is
);
return
arch_new_node
(
insn
,
irg
,
new_Unknown
(
mode_BB
),
mode_Is
,
arity
,
in
);
}
ir/be/bearch.h
0 → 100644
View file @
8e0086df
#ifndef _FIRM_BEARCH_H
#define _FIRM_BEARCH_H
#include "bitset.h"
/*
* Define the types of the arch facility.
* All arch object names are stored in bearch_obj.def
*/
#define ARCH_OBJ(x,list) typedef struct _arch_ ## x ## _t arch_ ## x ## _t;
#include "bearch_obj.def"
#undef ARCH_OBJ
/**
* A callback to determine the set of valid registers.
*
* @param irn The node which represents an instance of the instruction.
* @param pos The number of the insn's operand to consider.
* @param valid_regs A bitset where all valid registers are put.
*/
typedef
void
(
arch_register_callback_t
)(
ir_node
*
irn
,
int
pos
,
bitset_t
*
valid_regs
);
/**
* Add a new instruction set architecture.
* @param name The name of the isa.
* @return The isa object.
*/
arch_isa_t
*
arch_add_isa
(
const
char
*
name
);
/**
* Add a register class to the isa.
* @param isa The isa to add the reg class to.
* @param name The name of the register class.
* @param n_regs The number of registers in that class.
* @param mode The mode of the registers in that class.
*/
arch_register_class_t
*
arch_add_register_class
(
arch_isa_t
*
isa
,
const
char
*
name
,
int
n_regs
);
/**
* Add a register to a register class.
* @param cls The register class.
* @param index The index of the register (its number within the
* class).
* @param name The name of the register.
* @return The register.
*/
arch_register_t
*
arch_add_register
(
arch_register_class_t
*
cls
,
int
index
,
const
char
*
name
);
/**
* Add an immediate to the instruction set architecture.
* @param isa The isa.
* @param name The name of the immediate.
* @param mode The mode of the immediate.
* @return The immediate.
*/
arch_immediate_t
*
arch_add_immediate
(
arch_isa_t
*
isa
,
const
char
*
name
,
ir_mode
*
mode
);
/**
* Add an instruction format to an isa.
* @param isa The isa.
* @param name The name of the instruction format.
* @param n_in The number of in operands.
* @param n_out The number of out operands.
* @return The format.
*/
arch_insn_format_t
*
arch_add_insn_format
(
arch_isa_t
*
isa
,
const
char
*
name
,
int
n_in
,
int
n_out
);
/**
* Add a register set as an operand type.
* @param fmt The instruction format whose operand is to be set.
* @param pos The position of the operand. Note that input operands are
* numbered from 0 to n and output operands from -1 to -m.
* @param set The register set.
* @return The corresponding operand type.
*/
arch_operand_t
*
arch_add_operand_register_set
(
arch_insn_format_t
*
fmt
,
int
pos
,
const
arch_register_set_t
*
set
);
arch_operand_t
*
arch_add_operand_callback
(
arch_insn_format_t
*
fmt
,
int
pos
,
arch_register_callback_t
*
cb
);
arch_operand_t
*
arch_add_operand_immediate
(
arch_insn_format_t
*
fmt
,
int
pos
,
const
arch_immediate_t
*
imm
);
/**
* Add an instruction to the isa.
* @param fmt The instructon format.
* @param name The name of the instruction.
*/
arch_insn_t
*
arch_add_insn
(
arch_insn_format_t
*
fmt
,
const
char
*
name
);
/**
* Find an instruction format.
* @param isa The isa.
* @param name The name of the instruction format.
* @return The instruction format, if it was added before, or NULL if it
* is unknown.
*/
arch_insn_format_t
*
arch_find_insn_format
(
arch_isa_t
*
isa
,
const
char
*
name
);
/**
* Find an isa.
* @param name The name of the isa.
* @return The isa if it has been added, or NULl if it is unknwon.
*/
arch_isa_t
*
arch_find_isa
(
const
char
*
name
);
/**
* Find a register class of an isa.
* @param isa The isa.
* @param name The name of the register class.
* @return The register class, if it has been added, NULL if it is
* unknown.
*/
arch_register_class_t
*
arch_find_register_class
(
arch_isa_t
*
isa
,
const
char
*
name
);
/**
* Get the register set for a register class.
* Each register class possesses a set containing all registers known in
* the class.
* @param cls The class.
* @return The register set for the register class.
*/
arch_register_set_t
*
arch_get_register_set_for_class
(
arch_register_class_t
*
cls
);
#endif
ir/be/bearch_obj.def
0 → 100644
View file @
8e0086df
/*
The fields have following meaning:
1) Name of the object. This used to ## it to some pre- or suffix.
2) Boolean flag. If 1, the object shall be listed in a list whose
head is in the isa. This is useful, since we can generically
create lists of register classes, formats and so on.
*/
ARCH_OBJ(enum, 1)
ARCH_OBJ(enum_member, 0)
ARCH_OBJ(register, 0)
ARCH_OBJ(register_class, 1)
ARCH_OBJ(register_set, 1)
ARCH_OBJ(immediate, 0)
ARCH_OBJ(operand, 0)
ARCH_OBJ(insn_format, 1)
ARCH_OBJ(insn, 0)
ARCH_OBJ(isa, 0)
ir/be/bearch_t.h
0 → 100644
View file @
8e0086df
#ifndef _FIRM_BEARCH_T_H
#define _FIRM_BEARCH_T_H
#include "firm_config.h"
#include "irop_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "hashptr.h"
#include "fourcc.h"
#include "set.h"
#include "list.h"
#include "ident.h"
#include "bearch.h"
#define ARCH_IRN_FOURCC FOURCC('A', 'R', 'C', 'H')
/**
* Flags for registers.
*/
enum
{
/**
* The register is invariant concerning writes.
* Examples are the 0 registers in RISC architectures.
*/
REG_WRITE_INVARIAT
=
1
}
arch_register_flags_t
;
typedef
enum
{
#define ARCH_OBJ(x,list) arch_kind_##x,
#include "bearch_obj.def"
#undef ARCH_OBJ
arch_kind_last
}
arch_kind_t
;
/**
* A header which each of the arch structs should posess.
*/
typedef
struct
{
arch_kind_t
kind
;
arch_isa_t
*
isa
;
const
char
*
name
;
struct
list_head
list
;
unsigned
is_new
:
1
;
}
arch_header_t
;
/**
* Get the architecture an arch object belongs to.
* @param obj The object.
* @return The architecture it belongs to.
*/
static
INLINE
arch_isa_t
*
arch_obj_get_isa
(
const
void
*
obj
)
{
return
((
const
arch_header_t
*
)
obj
)
->
isa
;
}
typedef
enum
_arch_register_flag_t
{
arch_register_flag_none
,
arch_register_flag_caller_saved
,
/**< The register must be saved by the caller
upon a function call. It thus can be overwritten
in the called function. */
arch_register_flag_callee_saved
,
/**< The register must be saved by the called function,
it thus survives a function call. */
arch_register_flag_ignore
/**< Do not consider this register when allocating. */
}
arch_register_flag_t
;
/**
* A register.
*/
struct
_arch_register_t
{
arch_header_t
header
;
int
index
;
/**< The index of the register in the class. */
const
arch_register_class_t
*
reg_class
;
/**< The class the register belongs to. */
arch_register_flag_t
flags
;
/**< Flags describing several properties of
the register. */
};
/**
* A (sub-) set of registers.
*/
struct
_arch_register_set_t
{
arch_header_t
header
;
const
struct
_arch_register_class_t
*
reg_class
;
/**< The register class for this set. */
unsigned
comprises_full_class
:
1
;
/**< True, if all registers of the class
are contained in this set. */
int
regs
[
1
];
/**< An array containing 0/1 at place i
whether the register with index i is
in the set or not. */
};
static
INLINE
int
_arch_register_in_set
(
const
arch_register_set_t
*
set
,
const
arch_register_t
*
reg
)
{
if
(
reg
->
reg_class
!=
set
->
reg_class
)
return
0
;
return
set
->
regs
[
reg
->
index
];
}
/**
* A class of registers.
* Like general purpose or floating point.
*/
struct
_arch_register_class_t
{
arch_header_t
header
;
struct
list_head
list
;
/**< list head to list up in the list of all
register classes in an isa. */
arch_register_set_t
*
set
;
/**< A register set containing all registers
in this class. */
int
n_regs
;
/**< Number of registers in this class. */
arch_register_t
*
regs
[
1
];
/**< The array of registers. */
};
static
INLINE
const
arch_register_t
*
_arch_register_for_index
(
const
arch_register_class_t
*
cls
,
int
idx
)
{
assert
(
0
<=
idx
&&
idx
<=
cls
->
n_regs
);
return
cls
->
regs
[
idx
];
}
/**
* Get the register set for a register class.
* @param cls The register class.
* @return The set containing all registers in the class.
*/
static
INLINE
arch_register_set_t
*
_arch_get_register_set_for_class
(
const
arch_register_class_t
*
cls
)
{
return
cls
->
set
;
}
/**
* An immediate.
*/
struct
_arch_immediate_t
{
arch_header_t
header
;
ir_mode
*
mode
;
/**< The mode of the immediate. */
};
/**
* The member of an enum.
*/
struct
_arch_enum_member_t
{
arch_header_t
header
;
/**< The omnipresent header. */
arch_enum_t
*
enm
;
/**< The enum, this member belongs to. */
};
/**
* An enumeration operand type.
*
* Enumeration operand types can be used to describe the variants
* of an instruction, like giving the cases for a compare (gt, lt,
* eq, ...) some other special attributes of an instruction.
*/
struct
_arch_enum_t
{
arch_header_t
header
;
int
n_members
;
/**< The number of members in this enum. */
arch_enum_member_t
*
members
[
1
];
/**< The array of members. */
};
typedef
enum
_arch_operand_type_t
{
arch_operand_type_ir
=
0
,
arch_operand_type_variadic
,
arch_operand_type_symconst
,
arch_operand_type_register_set
,
arch_operand_type_immediate
}
arch_operand_type_t
;
/**
* The data for the different flavours of operand types.
*/
typedef
union
_arch_operand_data_t
{
arch_register_callback_t
*
callback
;
/**< The set of valid registers is determined
by a callback function. */
const
arch_register_set_t
*
set
;
/**< The set of valid registers is directly
given. Note, that if an insn has no constraints,
the set comprises all registers in the
register class. */
const
arch_immediate_t
*
imm
;
/**< If the operand is an immediate
operand, this describes the kind of
immediate. */
const
arch_enum_t
*
enm
;
/**< Some enumeration value. */
}
arch_operand_data_t
;