Add serde functionality into lib. (#422)
* Adds decoration to the verifier errors.
example:
function %bad(i32) fast {
ebb0(v0: i32):
brnz.i32 v0, ebb1
return
^~~~~~
verifier inst1: Internal return not allowed with return_at_end=1
ebb1:
trapz.i32 v0, user6
return
}
Fixes #68
* Making it so that pretty_function_error and write_function_plain are both private.
* Changes write_ebb to decorate_ebb.
Adds documentation line to decorate_function.
* Removing Cargo.toml lib/serde addition
* Add serde functionality into lib.
* Fix so code is compatible with Rust version 1.25.0.
* Move ser/de functions to utility file, update description, remove borrow from arms.
* Remove commented out code.
This commit is contained in:
committed by
Dan Gohman
parent
13fea26c95
commit
65a1a6bb28
@@ -17,6 +17,7 @@ cfg-if = "0.1"
|
|||||||
cranelift-codegen = { path = "lib/codegen", version = "0.17.0" }
|
cranelift-codegen = { path = "lib/codegen", version = "0.17.0" }
|
||||||
cranelift-reader = { path = "lib/reader", version = "0.17.0" }
|
cranelift-reader = { path = "lib/reader", version = "0.17.0" }
|
||||||
cranelift-frontend = { path = "lib/frontend", version = "0.17.0" }
|
cranelift-frontend = { path = "lib/frontend", version = "0.17.0" }
|
||||||
|
cranelift-serde = { path = "lib/serde", version = "0.17.0", optional = true }
|
||||||
cranelift-wasm = { path = "lib/wasm", version = "0.17.0", optional = true }
|
cranelift-wasm = { path = "lib/wasm", version = "0.17.0", optional = true }
|
||||||
cranelift-native = { path = "lib/native", version = "0.17.0" }
|
cranelift-native = { path = "lib/native", version = "0.17.0" }
|
||||||
cranelift-filetests = { path = "lib/filetests", version = "0.17.0" }
|
cranelift-filetests = { path = "lib/filetests", version = "0.17.0" }
|
||||||
|
|||||||
38
lib/serde/Cargo.toml
Normal file
38
lib/serde/Cargo.toml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
[package]
|
||||||
|
name = "cranelift-serde"
|
||||||
|
version = "0.17.0"
|
||||||
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
description = "Serializer/Deserializer for Cranelift IR"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["webassembly", "serde"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "clif-json"
|
||||||
|
path = "src/clif-json.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cfg-if = "0.1"
|
||||||
|
filecheck = "0.3.0"
|
||||||
|
docopt = "1"
|
||||||
|
serde = "1.0.8"
|
||||||
|
serde_derive = "1.0.8"
|
||||||
|
serde_json = "1.0"
|
||||||
|
term = "0.5.1"
|
||||||
|
target-lexicon = "0.0.2"
|
||||||
|
wasmparser = { version = "0.17.0", default-features = false }
|
||||||
|
cranelift-codegen = { path = "../codegen", version = "0.17.0", default-features = false }
|
||||||
|
cranelift-reader = { path = "../reader", version = "0.17.0", default-features = false }
|
||||||
|
cranelift-frontend = { path = "../frontend", version = "0.17.0", default-features = false }
|
||||||
|
failure = { version = "0.1.1", default-features = false, features = ["derive"] }
|
||||||
|
failure_derive = { version = "0.1.1", default-features = false }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmparser/std", "target-lexicon/std"]
|
||||||
|
core = ["cranelift-codegen/core", "cranelift-frontend/core", "wasmparser/core"]
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
30
lib/serde/README.md
Normal file
30
lib/serde/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
This crate performs serialization of the [Cranelift](https://crates.io/crates/cranelift) IR.
|
||||||
|
|
||||||
|
This crate is structured as an optional ability to serialize and deserialize cranelift IR into JSON format.
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
Cranelift IR can be serialized into JSON.
|
||||||
|
|
||||||
|
Deserialize is a work in progress, as it currently deserializes into the serializable data structure that can be utilized by serde instead of the actual Cranelift IR data structure.
|
||||||
|
|
||||||
|
|
||||||
|
Building and Using Cranelift Serde
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
clif-json usage:
|
||||||
|
|
||||||
|
clif-json serialize [-p] <file>
|
||||||
|
clif-json deserialize <file>
|
||||||
|
|
||||||
|
Where the -p flag outputs Cranelift IR as pretty JSON.
|
||||||
|
|
||||||
|
For example to build and use clif-json:
|
||||||
|
|
||||||
|
``` {.sourceCode .sh}
|
||||||
|
cd lib/serde
|
||||||
|
cargo build
|
||||||
|
clif-json serialize -p test.clif
|
||||||
|
```
|
||||||
|
|
||||||
121
lib/serde/src/clif-json.rs
Normal file
121
lib/serde/src/clif-json.rs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#![deny(trivial_numeric_casts)]
|
||||||
|
#![warn(unused_import_braces, unstable_features, unused_extern_crates)]
|
||||||
|
#![cfg_attr(
|
||||||
|
feature = "cargo-clippy",
|
||||||
|
warn(
|
||||||
|
float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
|
||||||
|
unicode_not_nfc, use_self
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
|
||||||
|
extern crate cranelift_reader;
|
||||||
|
extern crate docopt;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate cranelift_codegen;
|
||||||
|
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use cranelift_reader::parse_functions;
|
||||||
|
use docopt::Docopt;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
use std::process;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
mod serde_clif_json;
|
||||||
|
|
||||||
|
const USAGE: &str = "
|
||||||
|
Cranelift JSON serializer/deserializer utility
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
clif-json serialize [-p] <file>
|
||||||
|
clif-json deserialize <file>
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-p, --pretty print pretty json
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct Args {
|
||||||
|
cmd_serialize: bool,
|
||||||
|
cmd_deserialize: bool,
|
||||||
|
flag_pretty: bool,
|
||||||
|
arg_file: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A command either succeeds or fails with an error message.
|
||||||
|
pub type CommandResult = Result<(), String>;
|
||||||
|
|
||||||
|
fn call_ser(file: &str, pretty: bool) -> CommandResult {
|
||||||
|
let ret_of_parse = parse_functions(file);
|
||||||
|
match ret_of_parse {
|
||||||
|
Ok(funcs) => {
|
||||||
|
let ser_funcs = serde_clif_json::SerObj::new(&funcs);
|
||||||
|
let ser_str: String;
|
||||||
|
if pretty {
|
||||||
|
ser_str = serde_json::to_string_pretty(&ser_funcs).unwrap();
|
||||||
|
} else {
|
||||||
|
ser_str = serde_json::to_string(&ser_funcs).unwrap();
|
||||||
|
}
|
||||||
|
println!("{}", ser_str);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(_pe) => Err(format!("this was a parsing error")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_de(file: &File) -> CommandResult {
|
||||||
|
let de: serde_clif_json::SerObj = match serde_json::from_reader(file) {
|
||||||
|
Result::Ok(val) => val,
|
||||||
|
Result::Err(err) => panic!("{}", err),
|
||||||
|
};
|
||||||
|
println!("{:?}", de);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse the command line arguments and run the requested command.
|
||||||
|
fn clif_json() -> CommandResult {
|
||||||
|
// Parse command line arguments.
|
||||||
|
let args: Args = Docopt::new(USAGE)
|
||||||
|
.and_then(|d| d.help(true).deserialize())
|
||||||
|
.unwrap_or_else(|e| e.exit());
|
||||||
|
|
||||||
|
// Find the sub-command to execute.
|
||||||
|
let result = if args.cmd_serialize {
|
||||||
|
if let Some(first_file) = args.arg_file.first() {
|
||||||
|
let mut file = File::open(first_file).expect("Unable to open the file");
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents)
|
||||||
|
.expect("Unable to read the file");
|
||||||
|
call_ser(&contents, args.flag_pretty)
|
||||||
|
} else {
|
||||||
|
Err(format!("No file was passed"))
|
||||||
|
}
|
||||||
|
} else if args.cmd_deserialize {
|
||||||
|
if let Some(first_file) = args.arg_file.first() {
|
||||||
|
let mut file = File::open(first_file).expect("Unable to open the file");
|
||||||
|
call_de(&file)
|
||||||
|
} else {
|
||||||
|
Err(format!("No file was passed"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Debugging / shouldn't happen with proper command line handling above.
|
||||||
|
Err(format!("Unhandled args: {:?}", args))
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if let Err(mut msg) = clif_json() {
|
||||||
|
if !msg.ends_with('\n') {
|
||||||
|
msg.push('\n');
|
||||||
|
}
|
||||||
|
io::stdout().flush().expect("flushing stdout");
|
||||||
|
io::stderr().write_all(msg.as_bytes()).unwrap();
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
801
lib/serde/src/serde_clif_json.rs
Normal file
801
lib/serde/src/serde_clif_json.rs
Normal file
@@ -0,0 +1,801 @@
|
|||||||
|
use cranelift_codegen::ir::{Ebb, Function, Inst, InstructionData, Signature};
|
||||||
|
|
||||||
|
/// Serializable version of the original Cranelift IR
|
||||||
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum SerInstData {
|
||||||
|
Unary {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
},
|
||||||
|
UnaryImm {
|
||||||
|
opcode: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
UnaryIeee32 {
|
||||||
|
opcode: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
UnaryIeee64 {
|
||||||
|
opcode: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
UnaryBool {
|
||||||
|
opcode: String,
|
||||||
|
imm: bool,
|
||||||
|
},
|
||||||
|
UnaryGlobalValue {
|
||||||
|
opcode: String,
|
||||||
|
global_value: String,
|
||||||
|
},
|
||||||
|
Binary {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 2],
|
||||||
|
},
|
||||||
|
BinaryImm {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
Ternary {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 3],
|
||||||
|
},
|
||||||
|
MultiAry {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
},
|
||||||
|
NullAry {
|
||||||
|
opcode: String,
|
||||||
|
},
|
||||||
|
InsertLane {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 2],
|
||||||
|
lane: String,
|
||||||
|
},
|
||||||
|
ExtractLane {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
lane: String,
|
||||||
|
},
|
||||||
|
IntCompare {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 2],
|
||||||
|
cond: String,
|
||||||
|
},
|
||||||
|
IntCompareImm {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
cond: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
IntCond {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
cond: String,
|
||||||
|
},
|
||||||
|
FloatCompare {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 2],
|
||||||
|
cond: String,
|
||||||
|
},
|
||||||
|
FloatCond {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
cond: String,
|
||||||
|
},
|
||||||
|
IntSelect {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 3],
|
||||||
|
cond: String,
|
||||||
|
},
|
||||||
|
Jump {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
destination: String,
|
||||||
|
},
|
||||||
|
Branch {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
destination: String,
|
||||||
|
},
|
||||||
|
BranchInt {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
cond: String,
|
||||||
|
destination: String,
|
||||||
|
},
|
||||||
|
BranchFloat {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
cond: String,
|
||||||
|
destination: String,
|
||||||
|
},
|
||||||
|
BranchIcmp {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
cond: String,
|
||||||
|
destination: String,
|
||||||
|
},
|
||||||
|
BranchTable {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
table: String,
|
||||||
|
},
|
||||||
|
Call {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
func_ref: String,
|
||||||
|
},
|
||||||
|
CallIndirect {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
sig_ref: String,
|
||||||
|
},
|
||||||
|
FuncAddr {
|
||||||
|
opcode: String,
|
||||||
|
func_ref: String,
|
||||||
|
},
|
||||||
|
Load {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
flags: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
LoadComplex {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
flags: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
Store {
|
||||||
|
opcode: String,
|
||||||
|
args: [String; 2],
|
||||||
|
flags: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
StoreComplex {
|
||||||
|
opcode: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
flags: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
StackLoad {
|
||||||
|
opcode: String,
|
||||||
|
stack_slot: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
StackStore {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
stack_slot: String,
|
||||||
|
offset: String,
|
||||||
|
},
|
||||||
|
HeapAddr {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
heap: String,
|
||||||
|
imm: String,
|
||||||
|
},
|
||||||
|
RegMove {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
src: String,
|
||||||
|
dst: String,
|
||||||
|
},
|
||||||
|
CopySpecial {
|
||||||
|
opcode: String,
|
||||||
|
src: String,
|
||||||
|
dst: String,
|
||||||
|
},
|
||||||
|
RegSpill {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
src: String,
|
||||||
|
dst: String,
|
||||||
|
},
|
||||||
|
RegFill {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
src: String,
|
||||||
|
dst: String,
|
||||||
|
},
|
||||||
|
Trap {
|
||||||
|
opcode: String,
|
||||||
|
code: String,
|
||||||
|
},
|
||||||
|
CondTrap {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
code: String,
|
||||||
|
},
|
||||||
|
IntCondTrap {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
cond: String,
|
||||||
|
code: String,
|
||||||
|
},
|
||||||
|
FloatCondTrap {
|
||||||
|
opcode: String,
|
||||||
|
arg: String,
|
||||||
|
cond: String,
|
||||||
|
code: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_inst_data(inst_index: Inst, func: &Function) -> SerInstData {
|
||||||
|
let inst = &func.dfg[inst_index];
|
||||||
|
match *inst {
|
||||||
|
InstructionData::Unary { opcode, arg } => SerInstData::Unary {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::UnaryImm { opcode, imm } => SerInstData::UnaryImm {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::UnaryIeee32 { opcode, imm } => SerInstData::UnaryIeee32 {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::UnaryIeee64 { opcode, imm } => SerInstData::UnaryIeee64 {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::UnaryBool { opcode, imm } => SerInstData::UnaryBool {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
imm: imm,
|
||||||
|
},
|
||||||
|
InstructionData::UnaryGlobalValue {
|
||||||
|
opcode,
|
||||||
|
global_value,
|
||||||
|
} => SerInstData::UnaryGlobalValue {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
global_value: global_value.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::Binary { opcode, args } => {
|
||||||
|
let hold_args = [args[0].to_string(), args[1].to_string()];
|
||||||
|
SerInstData::Binary {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::BinaryImm { opcode, arg, imm } => SerInstData::BinaryImm {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::Ternary { opcode, args } => {
|
||||||
|
let hold_args = [
|
||||||
|
args[0].to_string(),
|
||||||
|
args[1].to_string(),
|
||||||
|
args[2].to_string(),
|
||||||
|
];
|
||||||
|
SerInstData::Ternary {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::MultiAry { opcode, ref args } => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
SerInstData::MultiAry {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::NullAry { opcode } => SerInstData::NullAry {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::InsertLane { opcode, args, lane } => {
|
||||||
|
let hold_args = [args[0].to_string(), args[1].to_string()];
|
||||||
|
SerInstData::InsertLane {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
lane: lane.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::ExtractLane { opcode, arg, lane } => SerInstData::ExtractLane {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
lane: lane.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::IntCompare { opcode, args, cond } => {
|
||||||
|
let hold_args = [args[0].to_string(), args[1].to_string()];
|
||||||
|
SerInstData::IntCompare {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::IntCompareImm {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
cond,
|
||||||
|
imm,
|
||||||
|
} => SerInstData::IntCompareImm {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
cond: cond.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::IntCond { opcode, arg, cond } => SerInstData::IntCond {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
cond: cond.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::FloatCompare { opcode, args, cond } => {
|
||||||
|
let hold_args = [args[0].to_string(), args[1].to_string()];
|
||||||
|
SerInstData::FloatCompare {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::FloatCond { opcode, arg, cond } => SerInstData::FloatCond {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
cond: cond.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::IntSelect { opcode, args, cond } => {
|
||||||
|
let hold_args = [
|
||||||
|
args[0].to_string(),
|
||||||
|
args[1].to_string(),
|
||||||
|
args[2].to_string(),
|
||||||
|
];
|
||||||
|
SerInstData::IntSelect {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::Jump {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
destination,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::Jump {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
destination: destination.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::Branch {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
destination,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::Branch {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
destination: destination.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::BranchInt {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
cond,
|
||||||
|
destination,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::BranchInt {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
destination: destination.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::BranchFloat {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
cond,
|
||||||
|
destination,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::BranchFloat {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
destination: destination.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::BranchIcmp {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
cond,
|
||||||
|
destination,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::BranchIcmp {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
cond: cond.to_string(),
|
||||||
|
destination: destination.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// to add: jump table serialization
|
||||||
|
InstructionData::BranchTable { opcode, arg, table } => SerInstData::BranchTable {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
table: table.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::Call {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
func_ref,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::Call {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
func_ref: func_ref.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::CallIndirect {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
sig_ref,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::CallIndirect {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
sig_ref: sig_ref.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::FuncAddr { opcode, func_ref } => SerInstData::FuncAddr {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
func_ref: func_ref.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::Load {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
flags,
|
||||||
|
offset,
|
||||||
|
} => SerInstData::Load {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
flags: flags.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::LoadComplex {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
flags,
|
||||||
|
offset,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::LoadComplex {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
flags: flags.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::Store {
|
||||||
|
opcode,
|
||||||
|
args,
|
||||||
|
flags,
|
||||||
|
offset,
|
||||||
|
} => {
|
||||||
|
let hold_args = [args[0].to_string(), args[1].to_string()];
|
||||||
|
SerInstData::Store {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
flags: flags.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::StoreComplex {
|
||||||
|
opcode,
|
||||||
|
ref args,
|
||||||
|
flags,
|
||||||
|
offset,
|
||||||
|
} => {
|
||||||
|
let mut hold_args = Vec::new();
|
||||||
|
let args_iter = args.as_slice(&func.dfg.value_lists);
|
||||||
|
for arg in args_iter {
|
||||||
|
hold_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
SerInstData::StoreComplex {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
args: hold_args,
|
||||||
|
flags: flags.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionData::StackLoad {
|
||||||
|
opcode,
|
||||||
|
stack_slot,
|
||||||
|
offset,
|
||||||
|
} => SerInstData::StackLoad {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
stack_slot: stack_slot.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::StackStore {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
stack_slot,
|
||||||
|
offset,
|
||||||
|
} => SerInstData::StackStore {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
stack_slot: stack_slot.to_string(),
|
||||||
|
offset: offset.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::HeapAddr {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
heap,
|
||||||
|
imm,
|
||||||
|
} => SerInstData::HeapAddr {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
heap: heap.to_string(),
|
||||||
|
imm: imm.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::RegMove {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
src,
|
||||||
|
dst,
|
||||||
|
} => SerInstData::RegMove {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
src: src.to_string(),
|
||||||
|
dst: dst.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::CopySpecial { opcode, src, dst } => SerInstData::CopySpecial {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
src: src.to_string(),
|
||||||
|
dst: dst.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::RegSpill {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
src,
|
||||||
|
dst,
|
||||||
|
} => SerInstData::RegSpill {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
src: src.to_string(),
|
||||||
|
dst: dst.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::RegFill {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
src,
|
||||||
|
dst,
|
||||||
|
} => SerInstData::RegFill {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
src: src.to_string(),
|
||||||
|
dst: dst.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::Trap { opcode, code } => SerInstData::Trap {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
code: code.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::CondTrap { opcode, arg, code } => SerInstData::CondTrap {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
code: code.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::IntCondTrap {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
cond,
|
||||||
|
code,
|
||||||
|
} => SerInstData::IntCondTrap {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
cond: cond.to_string(),
|
||||||
|
code: code.to_string(),
|
||||||
|
},
|
||||||
|
InstructionData::FloatCondTrap {
|
||||||
|
opcode,
|
||||||
|
arg,
|
||||||
|
cond,
|
||||||
|
code,
|
||||||
|
} => SerInstData::FloatCondTrap {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
cond: cond.to_string(),
|
||||||
|
code: code.to_string(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Serialize, Debug)]
|
||||||
|
pub struct SerInst {
|
||||||
|
pub inst_name: String,
|
||||||
|
pub inst_data: SerInstData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerInst {
|
||||||
|
pub fn new(inst: Inst, func: &Function) -> Self {
|
||||||
|
Self {
|
||||||
|
inst_name: inst.to_string(),
|
||||||
|
inst_data: get_inst_data(inst, func),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Serialize, Debug)]
|
||||||
|
pub struct SerEbb {
|
||||||
|
pub ebb: String,
|
||||||
|
pub params: Vec<String>,
|
||||||
|
pub insts: Vec<SerInst>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerEbb {
|
||||||
|
pub fn new(name: String) -> Self {
|
||||||
|
Self {
|
||||||
|
ebb: name,
|
||||||
|
params: Vec::new(),
|
||||||
|
insts: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_inst(func: &Function, ebb: Ebb) -> Vec<SerInst> {
|
||||||
|
let mut ser_vec: Vec<SerInst> = Vec::new();
|
||||||
|
let ret_iter = func.layout.ebb_insts(ebb);
|
||||||
|
for inst in ret_iter {
|
||||||
|
let mut ser_inst: SerInst = SerInst::new(inst, &func);
|
||||||
|
ser_vec.push(ser_inst);
|
||||||
|
}
|
||||||
|
ser_vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_params(func: &Function, ebb: &Ebb) -> Vec<String> {
|
||||||
|
let mut ser_vec: Vec<String> = Vec::new();
|
||||||
|
let parameters = func.dfg.ebb_params(*ebb);
|
||||||
|
for param in parameters {
|
||||||
|
ser_vec.push(param.to_string());
|
||||||
|
}
|
||||||
|
ser_vec
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializable Data Flow Graph
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct SerDataFlowGraph {
|
||||||
|
ebbs: Vec<SerEbb>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_ebbs(func: &Function) -> Vec<SerEbb> {
|
||||||
|
let mut ebb_vec: Vec<SerEbb> = Vec::new();
|
||||||
|
for ebb in func.layout.ebbs() {
|
||||||
|
let mut ser_ebb: SerEbb = SerEbb::new(ebb.to_string());
|
||||||
|
ser_ebb.params = populate_params(&func, &ebb);
|
||||||
|
ser_ebb.insts = populate_inst(&func, ebb);
|
||||||
|
ebb_vec.push(ser_ebb);
|
||||||
|
}
|
||||||
|
ebb_vec
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerDataFlowGraph {
|
||||||
|
pub fn create_new(func: &Function) -> Self {
|
||||||
|
Self {
|
||||||
|
ebbs: populate_ebbs(func),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(func: &Function) -> Self {
|
||||||
|
Self::create_new(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SerSignature {
|
||||||
|
pub func_params: Vec<String>,
|
||||||
|
pub func_returns: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerSignature {
|
||||||
|
fn create_new(sig: &Signature) -> Self {
|
||||||
|
let mut params_vec: Vec<String> = Vec::new();
|
||||||
|
let mut returns_vec: Vec<String> = Vec::new();
|
||||||
|
for param in sig.params.iter() {
|
||||||
|
params_vec.push(param.to_string());
|
||||||
|
}
|
||||||
|
for ret in sig.returns.iter() {
|
||||||
|
returns_vec.push(ret.to_string());
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
func_params: params_vec,
|
||||||
|
func_returns: returns_vec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(func: &Function) -> Self {
|
||||||
|
Self::create_new(&func.signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializable Function type
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SerFunction {
|
||||||
|
pub name: String,
|
||||||
|
pub signature: SerSignature,
|
||||||
|
pub globals: Vec<String>,
|
||||||
|
pub dfg: SerDataFlowGraph,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerFunction {
|
||||||
|
fn create_new(func: &Function) -> Self {
|
||||||
|
let mut global_vec: Vec<String> = Vec::new();
|
||||||
|
for (glob_name, _) in func.global_values.iter() {
|
||||||
|
global_vec.push(glob_name.to_string());
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
name: func.name.to_string(),
|
||||||
|
signature: SerSignature::new(&func),
|
||||||
|
globals: global_vec,
|
||||||
|
dfg: SerDataFlowGraph::new(&func),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(func: &Function) -> Self {
|
||||||
|
Self::create_new(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Must have SerObj for deserialization
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SerObj {
|
||||||
|
pub functions: Vec<SerFunction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerObj {
|
||||||
|
fn create_new(funcs: Vec<SerFunction>) -> Self {
|
||||||
|
Self { functions: funcs }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(funcs: &Vec<Function>) -> Self {
|
||||||
|
let mut func_vec: Vec<SerFunction> = Vec::new();
|
||||||
|
for func in funcs {
|
||||||
|
let mut ser_func: SerFunction = SerFunction::new(&func);
|
||||||
|
func_vec.push(ser_func);
|
||||||
|
}
|
||||||
|
Self::create_new(func_vec)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user