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):
|
||||
"""Generate opcode enumerations."""
|
||||
fmt = srcgen.Formatter()
|
||||
fmt.line('enum Opcode {')
|
||||
fmt.indent_push()
|
||||
for g in groups:
|
||||
for i in g.instructions:
|
||||
fmt.line(i.camel_name + ',')
|
||||
fmt.indent_pop()
|
||||
fmt.line('}')
|
||||
|
||||
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 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 + ',')
|
||||
|
||||
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)
|
||||
|
||||
def generate(targets, out_dir):
|
||||
|
||||
@@ -25,15 +25,15 @@ class Formatter(object):
|
||||
>>> f.indent_push()
|
||||
>>> f.comment('Nested comment')
|
||||
>>> f.indent_pop()
|
||||
>>> f.line('Back again')
|
||||
>>> f.format('Back {} again', 'home')
|
||||
>>> f.writelines()
|
||||
Hello line 1
|
||||
// Nested comment
|
||||
Back again
|
||||
// Nested comment
|
||||
Back home again
|
||||
|
||||
"""
|
||||
|
||||
shiftwidth = 2
|
||||
shiftwidth = 4
|
||||
|
||||
def __init__(self):
|
||||
self.indent = ''
|
||||
@@ -64,10 +64,49 @@ class Formatter(object):
|
||||
with open(filename, 'w') as 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):
|
||||
"""Add a comment line."""
|
||||
self.line('// ' + s)
|
||||
|
||||
def doc_comment(self, s):
|
||||
"""Add a documentation comment line."""
|
||||
self.line('/// ' + s)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
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.
|
||||
///
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
@@ -41,11 +44,13 @@ impl Display for Imm64 {
|
||||
/// An IEEE binary32 immediate floating point value.
|
||||
///
|
||||
/// All bit patterns are allowed.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Ieee32(f32);
|
||||
|
||||
/// An IEEE binary64 immediate floating point value.
|
||||
///
|
||||
/// All bit patterns are allowed.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Ieee64(f64);
|
||||
|
||||
// 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 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]
|
||||
fn format_imm64() {
|
||||
assert_eq!(format!("{}", Imm64(0)), "0");
|
||||
|
||||
Reference in New Issue
Block a user