Commit f179d707 authored by Matthias Braun's avatar Matthias Braun
Browse files

simplify asm constraint parsing

parent ff26d458
......@@ -35,7 +35,7 @@ typedef enum asm_constraint_flags_t {
ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP = 1u << 1,
/** input can be encoded as an immediate number */
ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE = 1u << 2,
/** the constraint is not supported yet by libFirm */
/** the constraint is not supported yet by libFirm (but valid in gcc) */
ASM_CONSTRAINT_FLAG_NO_SUPPORT = 1u << 3,
/** The input is also written to */
ASM_CONSTRAINT_FLAG_MODIFIER_WRITE = 1u << 4,
......
......@@ -267,12 +267,6 @@ static const backend_params *TEMPLATE_get_backend_params(void)
return &p;
}
static asm_constraint_flags_t TEMPLATE_parse_asm_constraint(const char **c)
{
(void) c;
return ASM_CONSTRAINT_FLAG_INVALID;
}
static int TEMPLATE_is_valid_clobber(const char *clobber)
{
(void) clobber;
......@@ -328,7 +322,6 @@ const arch_isa_if_t TEMPLATE_isa_if = {
TEMPLATE_finish,
TEMPLATE_get_backend_params,
TEMPLATE_lower_for_target,
TEMPLATE_parse_asm_constraint,
TEMPLATE_is_valid_clobber,
TEMPLATE_begin_codegeneration,
......
......@@ -405,12 +405,6 @@ static const backend_params *amd64_get_backend_params(void) {
return &p;
}
static asm_constraint_flags_t amd64_parse_asm_constraint(const char **c)
{
(void) c;
return ASM_CONSTRAINT_FLAG_INVALID;
}
static int amd64_is_valid_clobber(const char *clobber)
{
(void) clobber;
......@@ -449,7 +443,6 @@ const arch_isa_if_t amd64_isa_if = {
amd64_finish,
amd64_get_backend_params,
amd64_lower_for_target,
amd64_parse_asm_constraint,
amd64_is_valid_clobber,
amd64_begin_codegeneration,
......
......@@ -430,13 +430,6 @@ static int arm_is_mux_allowed(ir_node *sel, ir_node *mux_false,
return false;
}
static asm_constraint_flags_t arm_parse_asm_constraint(const char **c)
{
/* asm not supported */
(void) c;
return ASM_CONSTRAINT_FLAG_INVALID;
}
static int arm_is_valid_clobber(const char *clobber)
{
(void) clobber;
......@@ -525,7 +518,6 @@ const arch_isa_if_t arm_isa_if = {
arm_finish,
arm_get_libfirm_params,
arm_lower_for_target,
arm_parse_asm_constraint,
arm_is_valid_clobber,
arm_begin_codegeneration,
......
......@@ -67,8 +67,6 @@ struct be_main_env_t {
extern asm_constraint_flags_t asm_constraint_flags[256];
void be_init_default_asm_constraint_flags(void);
void be_get_allocatable_regs(ir_graph const *irg, arch_register_class_t const *cls, unsigned *raw_bitset);
unsigned be_get_n_allocatable_regs(const ir_graph *irg,
......
......@@ -394,13 +394,6 @@ struct arch_isa_if_t {
*/
void (*lower_for_target)(void);
/**
* parse an assembler constraint part and set flags according to its nature
* advances the *c pointer to point to the last parsed character (so if you
* parse a single character don't advance c)
*/
asm_constraint_flags_t (*parse_asm_constraint)(const char **c);
/**
* returns true if the string is a valid clobbered (register) in this
* backend
......
......@@ -33,6 +33,7 @@
#include "irprofile.h"
#include "irpass_t.h"
#include "ircons.h"
#include "util.h"
#include "bearch.h"
#include "be_t.h"
......@@ -127,10 +128,27 @@ static bool isa_initialized = false;
asm_constraint_flags_t asm_constraint_flags[256];
static void be_init_default_asm_constraint_flags(void)
{
/* list of constraints supported by gcc for any machine (or at least
* recognized). Mark them as NO_SUPPORT so we can differentiate them
* from INVALID. Backends should change the flags they support. */
static const unsigned char gcc_common_flags[] = {
'?', '!', '&', '%', 'i', 's', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'm', 'o', 'r', 'V', '<', '>', 'p', 'g', 'X',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};
for (size_t i = 0; i < ARRAY_SIZE(gcc_common_flags); ++i) {
unsigned char const c = gcc_common_flags[i];
asm_constraint_flags[c] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
}
}
static void initialize_isa(void)
{
if (isa_initialized)
return;
be_init_default_asm_constraint_flags();
isa_if->init();
isa_initialized = true;
}
......@@ -143,67 +161,6 @@ static void finish_isa(void)
}
}
void be_init_default_asm_constraint_flags(void)
{
asm_constraint_flags['?'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['&'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
| ASM_CONSTRAINT_FLAG_MODIFIER_EARLYCLOBBER;
asm_constraint_flags['%'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
| ASM_CONSTRAINT_FLAG_MODIFIER_COMMUTATIVE;
asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['='] = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
| ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
asm_constraint_flags['+'] = ASM_CONSTRAINT_FLAG_MODIFIER_READ
| ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
asm_constraint_flags['i'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['s'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['E'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['F'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['G'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['H'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['I'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['J'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['K'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['L'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['M'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['N'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['O'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['P'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['m'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['o'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['V'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['<'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['>'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['p'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['0'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['1'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['2'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['3'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['4'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['5'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['6'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['7'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['8'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['9'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
| ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP
| ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
/* these should have been catched by the parsing code already */
asm_constraint_flags['#'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['*'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags[' '] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['\t'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['\n'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['\r'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
}
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
{
asm_constraint_flags_t flags = ASM_CONSTRAINT_FLAG_NONE;
......@@ -214,26 +171,39 @@ asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
for (c = constraint; *c != '\0'; ++c) {
switch (*c) {
case ' ':
case '\t':
case '\n':
case '\r':
break;
case '=':
flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
flags |= ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
break;
case '+':
flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
break;
case '&':
case '%':
/* not really supported by libFirm yet */
flags |= ASM_CONSTRAINT_FLAG_NO_SUPPORT;
break;
case '#':
/* 'comment' stuff */
/* text until comma is a comment */
while (*c != 0 && *c != ',')
++c;
break;
case '*':
/* 'comment' character */
/* next character is a comment */
++c;
break;
case ' ':
case '\t':
case '\n':
case '\r':
break;
default:
tflags = asm_constraint_flags[(int) *c];
if (tflags != 0) {
flags |= tflags;
} else {
flags |= isa_if->parse_asm_constraint(&c);
flags |= ASM_CONSTRAINT_FLAG_INVALID;
}
break;
}
......
......@@ -1203,49 +1203,28 @@ extern const arch_isa_if_t ia32_isa_if;
static void init_asm_constraints(void)
{
be_init_default_asm_constraint_flags();
asm_constraint_flags['a'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['b'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['c'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['d'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['D'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['S'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['Q'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['q'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['A'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['l'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['R'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['r'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['p'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['f'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['t'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['u'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['Y'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['n'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['g'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
/* no support for autodecrement/autoincrement */
asm_constraint_flags['<'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['>'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* no float consts */
asm_constraint_flags['E'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['F'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* makes no sense on x86 */
asm_constraint_flags['s'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* no support for sse consts yet */
asm_constraint_flags['C'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* no support for x87 consts yet */
asm_constraint_flags['G'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* no support for mmx registers yet */
asm_constraint_flags['y'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* not available in 32bit mode */
asm_constraint_flags['Z'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
asm_constraint_flags['e'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
/* no code yet to determine register class needed... */
asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
static const unsigned char register_flags[] = {
'a', 'b', 'c', 'd', 'D', 'S', 'Q', 'q', 'A', 'l', 'R', 'r', 'p', 'f',
't', 'u', 'Y', 'X', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
for (size_t i = 0; i < ARRAY_SIZE(register_flags); ++i) {
unsigned char const c = register_flags[i];
asm_constraint_flags[c] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
}
static const unsigned char immediate_flags[] = {
'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
};
for (size_t i = 0; i < ARRAY_SIZE(immediate_flags); ++i) {
unsigned char const c = immediate_flags[i];
asm_constraint_flags[c] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
}
asm_constraint_flags['g'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
| ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
| ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['m'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['o'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
asm_constraint_flags['V'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
}
/**
......@@ -1792,15 +1771,6 @@ static void ia32_mark_remat(ir_node *node)
}
}
static asm_constraint_flags_t ia32_parse_asm_constraint(const char **c)
{
(void) c;
/* we already added all our simple flags to the flags modifier list in
* init, so this flag we don't know. */
return ASM_CONSTRAINT_FLAG_INVALID;
}
static int ia32_is_valid_clobber(const char *clobber)
{
return ia32_get_clobber_register(clobber) != NULL;
......@@ -1945,7 +1915,6 @@ const arch_isa_if_t ia32_isa_if = {
ia32_finish,
ia32_get_libfirm_params,
ia32_lower_for_target,
ia32_parse_asm_constraint,
ia32_is_valid_clobber,
ia32_begin_codegeneration,
......
......@@ -31,10 +31,12 @@
ir_heights_t *ia32_heights = NULL;
static int check_immediate_constraint(long val, char immediate_constraint_type)
static bool check_immediate_constraint(long val, char immediate_constraint_type)
{
switch (immediate_constraint_type) {
case 'i': return 1;
case 'g':
case 'i':
case 'n': return true;
case 'I': return 0 <= val && val <= 31;
case 'J': return 0 <= val && val <= 63;
......
......@@ -169,6 +169,25 @@ static sparc_isa_t sparc_isa_template = {
SPARC_FPU_ARCH_FPU, /* FPU architecture */
};
static void init_asm_constraints(void)
{
asm_constraint_flags['r'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['e'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['f'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
asm_constraint_flags['A'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['I'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
asm_constraint_flags['='] = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
| ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
asm_constraint_flags['+'] = ASM_CONSTRAINT_FLAG_MODIFIER_READ
| ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
/* Note there are many more flags in gcc which we can't properly support
* at the moment. see gcc/config/sparc/constraints.md
* Not supported: 'f', 'e', 'c', 'd', 'b', 'h', 'D', 'J', 'K',
* 'L', 'M', 'N', 'O', 'G', 'H', 'Q', 'R', 'S', 'T', 'U', 'W', 'Y' */
}
/**
* rewrite unsigned->float conversion.
* Sparc has no instruction for this so instead we do the following:
......@@ -375,6 +394,7 @@ static void sparc_handle_intrinsics(void)
static void sparc_init(void)
{
init_asm_constraints();
sparc_register_init();
sparc_create_opcodes(&sparc_irn_ops);
sparc_cconv_init();
......@@ -497,12 +517,6 @@ static const backend_params *sparc_get_backend_params(void)
return &p;
}
static asm_constraint_flags_t sparc_parse_asm_constraint(const char **c)
{
(void) c;
return ASM_CONSTRAINT_FLAG_INVALID;
}
static int sparc_is_valid_clobber(const char *clobber)
{
(void) clobber;
......@@ -571,7 +585,6 @@ const arch_isa_if_t sparc_isa_if = {
sparc_finish,
sparc_get_backend_params,
sparc_lower_for_target,
sparc_parse_asm_constraint,
sparc_is_valid_clobber,
sparc_begin_codegeneration,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment