Include generated Opcode enum in the immediates module.
Generate nice doc comments for the Opcode enum variants that 'cargo doc' will pick up. Include a `Display` trait implementation that prints the lower snake-case version of the opcode name.
This commit is contained in:
@@ -17,13 +17,31 @@ def collect_instr_groups(targets):
|
|||||||
def gen_opcodes(groups, out_dir):
|
def gen_opcodes(groups, out_dir):
|
||||||
"""Generate opcode enumerations."""
|
"""Generate opcode enumerations."""
|
||||||
fmt = srcgen.Formatter()
|
fmt = srcgen.Formatter()
|
||||||
fmt.line('enum Opcode {')
|
|
||||||
fmt.indent_push()
|
fmt.doc_comment('An instruction opcode.')
|
||||||
|
fmt.doc_comment('')
|
||||||
|
fmt.doc_comment('All instructions from all supported targets are present.')
|
||||||
|
fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]')
|
||||||
|
instrs = []
|
||||||
|
with fmt.indented('pub enum Opcode {', '}'):
|
||||||
for g in groups:
|
for g in groups:
|
||||||
for i in g.instructions:
|
for i in g.instructions:
|
||||||
|
instrs.append(i)
|
||||||
|
# Build a doc comment.
|
||||||
|
prefix = ', '.join(o.name for o in i.outs)
|
||||||
|
if prefix:
|
||||||
|
prefix = prefix + ' = '
|
||||||
|
suffix = ', '.join(o.name for o in i.ins)
|
||||||
|
fmt.doc_comment('`{}{} {}`.'.format(prefix, i.name, suffix))
|
||||||
|
# Enum variant itself.
|
||||||
fmt.line(i.camel_name + ',')
|
fmt.line(i.camel_name + ',')
|
||||||
fmt.indent_pop()
|
|
||||||
fmt.line('}')
|
with fmt.indented('impl Display for Opcode {', '}'):
|
||||||
|
with fmt.indented('fn fmt(&self, f: &mut Formatter) -> fmt::Result {', '}'):
|
||||||
|
with fmt.indented('f.write_str(match *self {', '})'):
|
||||||
|
for i in instrs:
|
||||||
|
fmt.format('Opcode::{} => "{}",', i.camel_name, i.name)
|
||||||
|
|
||||||
fmt.update_file('opcodes.rs', out_dir)
|
fmt.update_file('opcodes.rs', out_dir)
|
||||||
|
|
||||||
def generate(targets, out_dir):
|
def generate(targets, out_dir):
|
||||||
|
|||||||
@@ -25,15 +25,15 @@ class Formatter(object):
|
|||||||
>>> f.indent_push()
|
>>> f.indent_push()
|
||||||
>>> f.comment('Nested comment')
|
>>> f.comment('Nested comment')
|
||||||
>>> f.indent_pop()
|
>>> f.indent_pop()
|
||||||
>>> f.line('Back again')
|
>>> f.format('Back {} again', 'home')
|
||||||
>>> f.writelines()
|
>>> f.writelines()
|
||||||
Hello line 1
|
Hello line 1
|
||||||
// Nested comment
|
// Nested comment
|
||||||
Back again
|
Back home again
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
shiftwidth = 2
|
shiftwidth = 4
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.indent = ''
|
self.indent = ''
|
||||||
@@ -64,10 +64,49 @@ class Formatter(object):
|
|||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
self.writelines(f)
|
self.writelines(f)
|
||||||
|
|
||||||
|
class _IndentedScope(object):
|
||||||
|
def __init__(self, fmt, after):
|
||||||
|
self.fmt = fmt
|
||||||
|
self.after = after
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.fmt.indent_push();
|
||||||
|
|
||||||
|
def __exit__(self, t, v, tb):
|
||||||
|
self.fmt.indent_pop()
|
||||||
|
if self.after:
|
||||||
|
self.fmt.line(self.after)
|
||||||
|
|
||||||
|
def indented(self, before=None, after=None):
|
||||||
|
"""
|
||||||
|
Return a scope object for use with a `with` statement:
|
||||||
|
|
||||||
|
>>> f = Formatter()
|
||||||
|
>>> with f.indented('prefix {', '} suffix'):
|
||||||
|
... f.line('hello')
|
||||||
|
>>> f.writelines()
|
||||||
|
prefix {
|
||||||
|
hello
|
||||||
|
} suffix
|
||||||
|
|
||||||
|
The optional `before` and `after` parameters are surrounding lines
|
||||||
|
which are *not* indented.
|
||||||
|
"""
|
||||||
|
if before:
|
||||||
|
self.line(before)
|
||||||
|
return self._IndentedScope(self, after)
|
||||||
|
|
||||||
|
def format(self, fmt, *args):
|
||||||
|
self.line(fmt.format(*args))
|
||||||
|
|
||||||
def comment(self, s):
|
def comment(self, s):
|
||||||
"""Add a comment line."""
|
"""Add a comment line."""
|
||||||
self.line('// ' + s)
|
self.line('// ' + s)
|
||||||
|
|
||||||
|
def doc_comment(self, s):
|
||||||
|
"""Add a documentation comment line."""
|
||||||
|
self.line('/// ' + s)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
// The `Opcode` enum is generated from the meta instruction descriptions.
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/opcodes.rs"));
|
||||||
|
|
||||||
/// 64-bit immediate integer operand.
|
/// 64-bit immediate integer operand.
|
||||||
///
|
///
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
@@ -41,11 +44,13 @@ impl Display for Imm64 {
|
|||||||
/// An IEEE binary32 immediate floating point value.
|
/// An IEEE binary32 immediate floating point value.
|
||||||
///
|
///
|
||||||
/// All bit patterns are allowed.
|
/// All bit patterns are allowed.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Ieee32(f32);
|
pub struct Ieee32(f32);
|
||||||
|
|
||||||
/// An IEEE binary64 immediate floating point value.
|
/// An IEEE binary64 immediate floating point value.
|
||||||
///
|
///
|
||||||
/// All bit patterns are allowed.
|
/// All bit patterns are allowed.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Ieee64(f64);
|
pub struct Ieee64(f64);
|
||||||
|
|
||||||
// Format a floating point number in a way that is reasonably human-readable, and that can be
|
// Format a floating point number in a way that is reasonably human-readable, and that can be
|
||||||
@@ -155,6 +160,19 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::{f32, f64};
|
use std::{f32, f64};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn opcodes() {
|
||||||
|
let x = Opcode::Iadd;
|
||||||
|
let mut y = Opcode::Isub;
|
||||||
|
|
||||||
|
assert!(x != y);
|
||||||
|
y = Opcode::Iadd;
|
||||||
|
assert_eq!(x, y);
|
||||||
|
|
||||||
|
assert_eq!(format!("{:?}", Opcode::IaddImm), "IaddImm");
|
||||||
|
assert_eq!(format!("{}", Opcode::IaddImm), "iadd_imm");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_imm64() {
|
fn format_imm64() {
|
||||||
assert_eq!(format!("{}", Imm64(0)), "0");
|
assert_eq!(format!("{}", Imm64(0)), "0");
|
||||||
|
|||||||
Reference in New Issue
Block a user