Generate code to precompute predicates.

Each ISA predicate is assigned a bit the the Flags struct, and a corresponding
method is generated.
This commit is contained in:
Jakob Stoklund Olesen
2016-08-11 17:38:56 -07:00
parent 13d33d5a7a
commit c998c79fe8
5 changed files with 135 additions and 15 deletions

View File

@@ -12,7 +12,8 @@ def layout_group(sgrp):
"""
Layout the settings in sgrp, assigning byte and bit offsets.
Return the next unused byte offset.
Return the number of bytes needed for settings and the total number of
bytes needed when including predicates.
"""
# Byte offset where booleans are allocated.
bool_byte = -1
@@ -37,7 +38,20 @@ def layout_group(sgrp):
setting.byte_offset = next_byte
next_byte += 1
return next_byte
settings_size = next_byte
# Allocate bits for all the precomputed predicates.
for pred in sgrp.predicates:
# Allocate a bit from bool_byte.
if bool_bit > 7:
bool_byte = next_byte
next_byte += 1
bool_bit = 0
pred.byte_offset = bool_byte
pred.bit_offset = bool_bit
bool_bit += 1
return (settings_size, next_byte)
def gen_enum_types(sgrp, fmt):
@@ -84,6 +98,18 @@ def gen_getter(setting, fmt):
raise AssertionError("Unknown setting kind")
def gen_pred_getter(pred, fmt):
"""
Emit a getter for a pre-computed predicate.
"""
fmt.doc_comment('Computed predicate `{}`.'.format(pred.rust_predicate(0)));
proto = 'pub fn {}(&self) -> bool'.format(pred.name)
with fmt.indented(proto + ' {', '}'):
fmt.line('(self.bytes[{}] & (1 << {})) != 0'.format(
pred.byte_offset,
pred.bit_offset))
def gen_getters(sgrp, fmt):
"""
Emit getter functions for all the settings in fmt.
@@ -92,6 +118,8 @@ def gen_getters(sgrp, fmt):
with fmt.indented('impl Flags {', '}'):
for setting in sgrp.settings:
gen_getter(setting, fmt)
for pred in sgrp.predicates:
gen_pred_getter(pred, fmt)
def gen_descriptors(sgrp, fmt):
@@ -147,11 +175,11 @@ def gen_descriptors(sgrp, fmt):
fmt.line('{},'.format(h.descriptor_index))
def gen_template(sgrp, byte_size, fmt):
def gen_template(sgrp, settings_size, fmt):
"""
Emit a Template constant.
"""
v = [0] * byte_size
v = [0] * settings_size
for setting in sgrp.settings:
v[setting.byte_offset] |= setting.default_byte()
@@ -189,50 +217,79 @@ def gen_display(sgrp, fmt):
fmt.line('Ok(())')
def gen_constructor(sgrp, byte_size, parent, fmt):
def gen_constructor(sgrp, settings_size, byte_size, parent, fmt):
"""
Generate a Flags constructor.
"""
with fmt.indented('impl Flags {', '}'):
with fmt.indented('pub fn new(builder: Builder) -> Flags {', '}'):
args = 'builder: Builder'
if sgrp.parent:
p = sgrp.parent
args = '{}: &{}::Flags, {}'.format(p.name, p.qual_mod, args)
with fmt.indented(
'pub fn new({}) -> Flags {{'.format(args), '}'):
fmt.line('let bvec = builder.finish("{}");'.format(sgrp.name))
fmt.line('let mut bytes = [0; {}];'.format(byte_size))
fmt.line('assert_eq!(bytes.len(), bvec.len());')
fmt.line('assert_eq!(bytes.len(), {});'.format(settings_size))
with fmt.indented(
'for (i, b) in bvec.into_iter().enumerate() {', '}'):
fmt.line('bytes[i] = b;')
fmt.line('Flags { bytes: bytes }')
# Stop here without predicates.
if len(sgrp.predicates) == 0:
fmt.line('Flags { bytes: bytes }')
return
# Now compute the predicates.
fmt.line(
'let mut {} = Flags {{ bytes: bytes }};'
.format(sgrp.name))
for pred in sgrp.predicates:
fmt.comment('Precompute: {}.'.format(pred.name))
with fmt.indented(
'if {} {{'.format(pred.rust_predicate(0)),
'}'):
fmt.line(
'{}.bytes[{}] |= 1 << {};'
.format(
sgrp.name, pred.byte_offset, pred.bit_offset))
fmt.line(sgrp.name)
def gen_group(sgrp, fmt):
"""
Generate a Flags struct representing `sgrp`.
"""
byte_size = layout_group(sgrp)
settings_size, byte_size = layout_group(sgrp)
fmt.line('#[derive(Clone)]')
fmt.doc_comment('Flags group `{}`.'.format(sgrp.name))
with fmt.indented('pub struct Flags {', '}'):
fmt.line('bytes: [u8; {}],'.format(byte_size))
fmt.line('bytes: [u8; {}],'.format(settings_size))
gen_constructor(sgrp, byte_size, None, fmt)
gen_constructor(sgrp, settings_size, byte_size, None, fmt)
gen_enum_types(sgrp, fmt)
gen_getters(sgrp, fmt)
gen_descriptors(sgrp, fmt)
gen_template(sgrp, byte_size, fmt)
gen_template(sgrp, settings_size, fmt)
gen_display(sgrp, fmt)
def generate(isas, out_dir):
# Generate shared settings.
fmt = srcgen.Formatter()
settings.group.qual_mod = 'settings'
gen_group(settings.group, fmt)
fmt.update_file('settings.rs', out_dir)
# Generate ISA-specific settings.
for isa in isas:
if isa.settings:
isa.settings.qual_mod = 'isa::{}::settings'.format(
isa.settings.name)
fmt = srcgen.Formatter()
gen_group(isa.settings, fmt)
fmt.update_file('settings-{}.rs'.format(isa.name), out_dir)