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
40cbede7
Commit
40cbede7
authored
Jul 24, 2015
by
Christoph Mallon
Browse files
bescripts: Clean up be node generators.
parent
38535d73
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
ir/be/scripts/generate_emitter.pl
View file @
40cbede7
#!/usr/bin/perl
-w
#!
/usr/bin/
env
perl
#
# This file is part of libFirm.
...
...
@@ -7,10 +7,10 @@
# This script generates C code which emits assembler code for the
# assembler ir nodes. It takes a "emit" key from the node specification
# and
substitutes lines starting with . with a corresponding fprintf()
.
# and
generates ${arch}_emitf() calls for them
.
use
strict
;
use
Data::
Dumper
;
use
warnings
;
our
$specfile
=
$ARGV
[
0
];
our
$target_dir
=
$ARGV
[
1
];
...
...
@@ -18,90 +18,77 @@ our $target_dir = $ARGV[1];
our
$arch
;
our
%nodes
;
my
$return
;
no
strict
"
subs
";
unless
(
$return
=
do
$specfile
)
{
unless
(
my
$return
=
do
$specfile
)
{
die
"
Fatal error: couldn't parse
$specfile
: $@
"
if
$@
;
die
"
Fatal error: couldn't do
$specfile
: $!
"
unless
defined
$return
;
die
"
Fatal error: couldn't run
$specfile
"
unless
$return
;
}
use
strict
"
subs
";
my
$target_c
=
$target_dir
.
"
/gen_
"
.
$arch
.
"
_emitter.c
";
my
$target_h
=
$target_dir
.
"
/gen_
"
.
$arch
.
"
_emitter.h
";
# buffers for output
my
$obst_func
=
"";
# buffer for the emit functions
my
$obst_register
=
"";
# buffer for emitter register code
foreach
my
$op
(
sort
(
keys
(
%nodes
)))
{
my
%
n
=
%
{
$nodes
{
"
$op
"}
};
my
$
n
=
$nodes
{
$op
};
# skip this node description if no emit information is available
next
if
(
!
defined
(
$n
{"
emit
"}));
if
(
$n
{"
emit
"}
eq
"")
{
$obst_register
.=
"
\t
be_set_emitter(op_
${arch}
_
${op}
, be_emit_nothing);
\n
";
my
$emit
=
$n
->
{
emit
};
if
(
!
defined
(
$emit
))
{
# no emit information is available, skip this node description
next
;
}
$obst_register
.=
"
\t
be_set_emitter(op_
${arch}
_
${op}
, emit_
${arch}
_
${op}
);
\n
";
$obst_func
.=
"
static void emit_
${arch}
_
${op}
(ir_node const *const node)
\n
";
$obst_func
.=
"
{
\n
";
my
@emit
=
split
(
/\n/
,
$n
{"
emit
"});
foreach
my
$template
(
@emit
)
{
if
(
$template
ne
'')
{
$obst_func
.=
"
\t
${arch}
_emitf(node,
\"
$template
\"
);
\n
";
my
$emit_func
;
if
(
$emit
eq
"")
{
$emit_func
=
"
be_emit_nothing
";
}
else
{
$emit_func
=
"
emit_
${arch}
_
$op
";
$obst_func
.=
"
static void
$emit_func
(ir_node const *const node)
\n
";
$obst_func
.=
"
{
\n
";
foreach
my
$template
(
split
(
/\n/
,
$emit
))
{
if
(
$template
ne
'')
{
$obst_func
.=
"
\t
${arch}
_emitf(node,
\"
$template
\"
);
\n
";
}
}
$obst_func
.=
"
}
\n\n
";
}
$obst_func
.=
"
}
\n\n
";
$obst_register
.=
"
\t
be_set_emitter(op_
${arch}
_
$op
,
$emit_func
);
\n
";
}
open
(
OUT
,
"
>
$target_h
")
||
die
("
Could not open
$target_h
, reason: $!
\n
");
my
$creation_time
=
localtime
(
time
());
my
$tmp
=
uc
(
$arch
);
sub
create_with_header
{
my
(
$name
,
$brief
)
=
@_
;
print
OUT
<<EOF;
open
(
my
$out
,
"
>
",
$name
)
//
die
("
Could not open
$name
, reason: $!
\n
");
print
$out
<<EOF;
/**
* \@file
* \@brief
Function prototypes for the emitter functions.
* \@brief
$brief
* \@note DO NOT EDIT THIS FILE, your changes will be lost.
* Edit $specfile instead.
* created by: $0 $specfile $target_dir
*
Edit $specfile instead.
*
created by: $0 $specfile $target_dir
* \@date $creation_time
*/
#ifndef FIRM_BE_${tmp}_GEN_${tmp}_EMITTER_H
#define FIRM_BE_${tmp}_GEN_${tmp}_EMITTER_H
EOF
return
$out
;
}
my
$out_h
=
create_with_header
("
$target_dir
/gen_
${arch}
_emitter.h
",
"
Function prototypes for the emitter functions.
");
my
$uarch
=
uc
(
$arch
);
print
$out_h
<<EOF;
#ifndef FIRM_BE_${uarch}_GEN_${uarch}_EMITTER_H
#define FIRM_BE_${uarch}_GEN_${uarch}_EMITTER_H
void ${arch}_register_spec_emitters(void);
#endif
EOF
close
(
$out_h
);
close
(
OUT
);
open
(
OUT
,
"
>
$target_c
")
||
die
("
Could not open
$target_c
, reason: $!
\n
");
$creation_time
=
localtime
(
time
());
print
OUT
<<EOF;
/**
* \@file
* \@brief Generated functions to emit code for assembler ir nodes.
* \@note DO NOT EDIT THIS FILE, your changes will be lost.
* Edit $specfile instead.
* created by: $0 $specfile $target_dir
* \@date $creation_time
*/
my
$out_c
=
create_with_header
("
$target_dir
/gen_
${arch}
_emitter.c
",
"
Generated functions to emit code for assembler ir nodes.
");
print
$out_c
<<EOF;
#include "beemitter.h"
#include "gen_${arch}_emitter.h"
#include "${arch}_new_nodes.h"
...
...
@@ -113,11 +100,9 @@ $obst_func
* Enters the emitter functions for handled nodes into the generic
* pointer of an opcode.
*/
void $arch
\
_register_spec_emitters(void)
void $
{
arch
}
_register_spec_emitters(void)
{
$obst_register
}
EOF
close
(
OUT
);
close
(
$out_c
);
ir/be/scripts/generate_new_opcodes.pl
View file @
40cbede7
This diff is collapsed.
Click to expand it.
ir/be/scripts/generate_regalloc_if.pl
View file @
40cbede7
#!/usr/bin/perl
-w
#!
/usr/bin/
env
perl
#
# This file is part of libFirm.
...
...
@@ -7,11 +7,10 @@
# This script generates C code which creates ands sets up functions and
# data structures for the register allocator.
# Creation: 2005/11/14
use
strict
;
use
Data::
Dumper
;
use
integer
;
use
strict
;
use
warnings
;
my
$specfile
=
$ARGV
[
0
];
my
$target_dir
=
$ARGV
[
1
];
...
...
@@ -20,23 +19,15 @@ our $arch;
our
%reg_classes
;
# include spec file
my
$return
;
use
strict
"
subs
";
unless
(
$return
=
do
$specfile
)
{
unless
(
my
$return
=
do
$specfile
)
{
die
"
Fatal error: couldn't parse
$specfile
: $@
"
if
$@
;
die
"
Fatal error: couldn't do
$specfile
: $!
"
unless
defined
$return
;
die
"
Fatal error: couldn't run
$specfile
"
unless
$return
;
}
use
strict
"
subs
";
my
$target_c
=
$target_dir
.
"
/gen_
"
.
$arch
.
"
_regalloc_if.c
";
my
$target_h
=
$target_dir
.
"
/gen_
"
.
$arch
.
"
_regalloc_if.h
";
# stacks for output
my
$regtypes_def
;
# stack for the register type variables definitions
my
@
regclasses
;
# stack for the register class variables
my
$
regclasses
;
# stack for the register class variables
my
$classdef
;
# stack to define a name for a class index
my
$reqdecls
;
my
$regdef
;
# stack to define a name for a register index
...
...
@@ -45,20 +36,16 @@ my $regcounts;
my
$reginit
;
# stack for the register type inits
my
$single_constraints
;
my
$class_idx
=
0
;
my
%regclass2len
=
();
my
%reg2class
=
();
$classdef
.=
"
enum reg_classes {
\n
";
foreach
my
$class_name
(
sort
(
keys
(
%reg_classes
)))
{
my
@class
=
@
{
$reg_classes
{
"
$class_name
"
}
};
my
@class
=
@
{
$reg_classes
{
$class_name
}
};
my
$idx
=
0
;
foreach
(
@class
)
{
if
(
defined
(
$_
->
{
name
}))
{
$reg2class
{
$
_
->
{
name
}
}
=
{
if
(
defined
(
my
$name
=
$_
->
{
name
}))
{
$reg2class
{
$name
}
=
{
"
class
"
=>
$class_name
,
"
index
"
=>
$idx
};
...
...
@@ -68,29 +55,27 @@ foreach my $class_name (sort(keys(%reg_classes))) {
$regclass2len
{
$class_name
}
=
$idx
;
}
sub
get_limited_array
{
my
$reg
=
shift
;
my
$regclass
=
$reg2class
{"
$reg
"}{"
class
"};
my
$ucname
=
uc
(
$reg
);
my
$result
=
"
{
";
sub
get_limited_array
{
my
(
$reg
)
=
@_
;
my
$limitedbitsetlen
=
$regclass2len
{
$regclass
};
my
$arraylen
=
(
$limitedbitsetlen
+
31
)
/
32
;
my
$result
=
"
{
";
my
$sep
=
"";
my
$regclass
=
$reg2class
{
$reg
}{
class
};
my
$classuc
=
uc
(
$regclass
);
my
$first
=
1
;
my
$ucname
=
uc
(
$reg
);
my
$limitedbitsetlen
=
$regclass2len
{
$regclass
};
my
$arraylen
=
(
$limitedbitsetlen
+
31
)
/
32
;
for
(
my
$i
=
0
;
$i
<
$arraylen
;
++
$i
)
{
if
(
$first
)
{
$first
=
0
;
}
else
{
$result
.=
"
,
";
}
$result
.=
$sep
;
$sep
=
"
,
";
my
$index
=
$reg2class
{
"
$reg
"
}{
"
index
"
};
if
(
$i
ndex
>=
$i
*
32
&&
$index
<
(
$i
+
1
)
*
32
)
{
my
$index
=
$reg2class
{
$reg
}{
index
};
if
(
$i
*
32
<=
$index
&&
$index
<
(
$i
+
1
)
*
32
)
{
if
(
$i
>
0
)
{
$result
.=
"
(1 << (REG_
${classuc}
_
${ucname}
% 32))
";
$result
.=
"
(1
U
<< (REG_
${classuc}
_
${ucname}
% 32))
";
}
else
{
$result
.=
"
(1 << REG_
${classuc}
_
${ucname}
)
";
$result
.=
"
(1
U
<< REG_
${classuc}
_
${ucname}
)
";
}
}
else
{
$result
.=
"
0
";
...
...
@@ -99,115 +84,105 @@ sub get_limited_array {
$result
.=
"
}
";
}
sub
has_flag
{
my
(
$what
,
$list
)
=
@_
;
return
(
defined
(
$list
)
&&
grep
{
$_
eq
$what
}
$list
)
?
"
true
"
:
"
false
";
}
# generate register type and class variable, init function and default requirements
foreach
my
$class_name
(
sort
(
keys
(
%reg_classes
)))
{
my
@class
=
@
{
$reg_classes
{"
$class_name
"}
};
my
$old_classname
=
$class_name
;
my
@class
=
@
{
$reg_classes
{
$class_name
}
};
$class_name
=
$arch
.
"
_
"
.
$class_name
;
my
$class_ptr
=
"
&
"
.
$arch
.
"
_reg_classes[CLASS_
"
.
$class_name
.
"
]
";
my
$flags
=
pop
(
@class
);
my
$class_mode
=
$flags
->
{"
mode
"};
my
$arch_class_name
=
"
${arch}
_
$class_name
";
my
$class_req
=
"
${arch}
_class_reg_req_
$class_name
";
my
$class_enum
=
"
CLASS_
$arch_class_name
";
my
$class_ptr
=
"
&
${arch}
_reg_classes[
$class_enum
]
";
my
$flags
=
pop
(
@class
);
my
$class_mode
=
$flags
->
{
mode
};
$single_constraints
.=
<<EOF;
const arch_register_req_t $
{arch}_
class_re
g_req_${old_classname}
= {
.cls = &${arch}_reg_classes[
CLASS_${arch}_${old_classname}
],
const arch_register_req_t $class_re
q
= {
.cls = &${arch}_reg_classes[
$class_enum
],
.width = 1,
};
EOF
$reqdecls
.=
"
extern const arch_register_req_t
${arch}
_class_reg_req_
${old_classname}
;
\n
";
$classdef
.=
"
\t
CLASS_
$class_name
=
$class_idx
,
\n
";
my
$numregs
=
@class
;
my
$manual_ra
=
"
false
";
for
(
$flags
->
{"
flags
"})
{
if
(
defined
(
$_
)
&&
$_
eq
"
manual_ra
")
{
$manual_ra
=
"
true
";
}
}
my
$first_reg
=
"
&
${arch}
_registers[REG_
"
.
uc
(
$class
[
0
]
->
{"
name
"})
.
"
]
";
my
$rcdef
=
<<EOF;
$reqdecls
.=
"
extern const arch_register_req_t
$class_req
;
\n
";
$classdef
.=
"
\t
$class_enum
,
\n
";
my
$numregs
=
@class
;
my
$manual_ra
=
has_flag
("
manual_ra
",
$flags
->
{
flags
});
my
$uname
=
uc
(
$class
[
0
]
->
{
name
});
$regclasses
.=
<<EOF;
{
.name = \"$class_name\",
.name = \"$
arch_
class_name\",
.mode = NULL,
.regs =
$first_reg
,
.class_req = &$
{arch}_
class_re
g_req_${old_classname}
,
.index = $class_
idx
,
.regs =
&${arch}_registers[REG_$uname]
,
.class_req = &$class_re
q
,
.index = $class_
enum
,
.n_regs = $numregs,
.manual_ra = $
{
manual_ra
}
,
.manual_ra = $manual_ra,
},
EOF
push
(
@regclasses
,
$rcdef
);
my
$idx
=
0
;
$reg
init
.=
"
\t
$arch
\
_reg_classes[CLASS_
"
.
$class_name
.
"
].mode =
$class_mode
;
\n
";
$reginit
.=
"
\t
$arch
\
_reg_classes[
$class_enum
].mode =
$class_mode
;
\n
"
;
$reg
def2
.=
"
enum {
\n
";
foreach
(
@class
)
{
my
$name
=
$_
->
{"
name
"};
my
$ucname
=
uc
(
$name
);
my
$is_virtual
=
"
false
";
for
(
$_
->
{"
type
"})
{
if
(
defined
(
$_
)
&&
$_
eq
"
virtual
")
{
$is_virtual
=
"
true
";
}
}
my
$name
=
$_
->
{
name
};
# realname is name if not set by user
$_
->
{"
realname
"}
=
$_
->
{"
name
"}
if
(
!
exists
(
$_
->
{"
realname
"}));
my
$realname
=
$_
->
{
realname
};
my
$classuc
=
uc
(
$old_classname
);
$regdef
.=
"
\t
REG_
${ucname}
,
\n
";
$regdef2
.=
"
\t
REG_
${classuc}
_
${ucname}
=
$idx
,
\n
";
my
$dwarf_number
=
0
;
if
(
defined
(
$_
->
{
dwarf
}))
{
$dwarf_number
=
$_
->
{
dwarf
};
}
my
$encoding
=
"
REG_
${classuc}
_
${ucname}
";
if
(
defined
(
$_
->
{
encoding
}))
{
$encoding
=
$_
->
{
encoding
};
}
my
$realname
=
$_
->
{
realname
}
//
$name
;
my
$single_req
=
"
${arch}
_single_reg_req_
${class_name}
_
${name}
";
my
$classuc
=
uc
(
$class_name
);
my
$ucname
=
uc
(
$name
);
my
$local_idx
=
"
REG_
${classuc}
_
$ucname
";
my
$global_idx
=
"
REG_
$ucname
";
my
$dwarf_number
=
$_
->
{
dwarf
}
//
0
;
my
$encoding
=
$_
->
{
encoding
}
//
$local_idx
;
my
$is_virtual
=
has_flag
("
virtual
",
$_
->
{
type
});
$regdef
.=
"
\t
$global_idx
,
\n
";
$regdef2
.=
"
\t
$local_idx
,
\n
";
$regtypes_def
.=
<<EOF;
{
.name = "$
{
realname
}
",
.cls = $
{
class_ptr
}
,
.single_req = &$
{arch}_
single_re
g_req_${old_classname}_${name}
,
.index =
REG_${classuc}_${ucname}
,
.global_index =
REG_${ucname}
,
.dwarf_number = $
{
dwarf_number
}
,
.encoding = $
{
encoding
}
,
.is_virtual = $
{
is_virtual
}
,
.name = "$realname",
.cls = $class_ptr,
.single_req = &$single_re
q
,
.index =
$local_idx
,
.global_index =
$global_idx
,
.dwarf_number = $dwarf_number,
.encoding = $encoding,
.is_virtual = $is_virtual,
},
EOF
my
$limited_name
=
"
${arch}
_limited_
${class_name}
_
${name}
";
my
$limitedarray
=
get_limited_array
(
$name
);
$single_constraints
.=
<<EOF;
static const unsigned ${
arch}_
limited_
${old_classname}_${name}
[] = $
{
limitedarray
}
;
const arch_register_req_t $
{arch}_
single_re
g_req_${old_classname}_${name}
= {
.cls = $
{
class_ptr
}
,
.limited = $
{arch}_
limited_
${old_classname}_${name}
,
static const unsigned ${limited_
name}
[] = $limitedarray;
const arch_register_req_t $single_re
q
= {
.cls = $class_ptr,
.limited = $limited_
name
,
.width = 1,
};
EOF
$reqdecls
.=
"
extern const arch_register_req_t
${arch}
_single_reg_req_
${old_classname}
_
${name}
;
\n
";
$idx
++
;
$reqdecls
.=
"
extern const arch_register_req_t
$single_req
;
\n
";
}
$regcounts
.=
"
\t
N_
${class_name}
_REGS =
$numregs
,
\n
";
$class_idx
++
;
$regdef2
.=
"
};
\n\n
";
$regcounts
.=
"
\t
N_
${arch_class_name}
_REGS =
$numregs
,
\n
";
}
my
$archuc
=
uc
(
$arch
);
$classdef
.=
"
\t
N_
${archuc}
_CLASSES =
"
.
scalar
(
keys
(
%reg_classes
))
.
"
\n
";
$classdef
.=
"
};
\n\n
";
# generate header (external usage) file
open
(
OUT
,
"
>
$target_h
")
||
die
("
Fatal error: Could not open
$target_h
, reason: $!
\n
");
$classdef
.=
"
\t
N_
${archuc}
_CLASSES =
"
.
scalar
(
keys
(
%reg_classes
));
my
$creation_time
=
localtime
(
time
());
print
OUT
<<EOF;
# generate header (external usage) file
my
$target_h
=
"
$target_dir
/gen_
${arch}
_regalloc_if.h
";
open
(
OUT
,
"
>
",
$target_h
)
//
die
("
Fatal error: Could not open
$target_h
, reason: $!
\n
");
print
OUT
<<EOF;
/**
* \@file
* \@brief Contains additional external requirements defs for external includes.
...
...
@@ -227,16 +202,17 @@ enum reg_indices {
${regdef}
N_${archuc}_REGISTERS
};
/** local register indices for ${arch} registers */
enum {
${regdef2}
};
/** number of registers in ${arch} register classes. */
enum {
${regcounts}
};
enum {
${classdef}
};
${reqdecls}
...
...
@@ -250,13 +226,10 @@ void ${arch}_register_init(void);
EOF
close
(
OUT
);
# generate c file
open
(
OUT
,
"
>
$target_c
")
||
die
("
Fatal error: Could not open
$target_c
, reason: $!
\n
");
$creation_time
=
localtime
(
time
());
print
OUT
<<EOF;
my
$target_c
=
"
$target_dir
/gen_
${arch}
_regalloc_if.c
";
open
(
OUT
,
"
>
",
$target_c
)
//
die
("
Fatal error: Could not open
$target_c
, reason: $!
\n
");
print
OUT
<<EOF;
/**
* \@file
* \@brief The generated interface for the register allocator.
...
...
@@ -271,11 +244,10 @@ print OUT<<EOF;
#include "bearch_${arch}_t.h"
${single_constraints}
EOF
print
OUT
"
arch_register_class_t
${arch}
_reg_classes[] = {
\n
"
.
join
("",
@regclasses
)
.
"
\n
};
\n\n
";
print
OUT
<<EOF
;
arch_register_class_t ${arch}_reg_classes[] = {
$regclasses
}
;
/** The array of all registers in the ${arch} architecture, sorted by its global index.*/
const arch_register_t ${arch}_registers[] = {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment