1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use super::{DataSection, InstructionSet};
use crate::asm_lang::allocated_ops::AllocatedOpcode;
use crate::error::*;
use sway_types::span::Span;
use either::Either;
use std::io::Read;
#[derive(Clone)]
pub enum FinalizedAsm {
ContractAbi {
data_section: DataSection,
program_section: InstructionSet,
},
ScriptMain {
data_section: DataSection,
program_section: InstructionSet,
},
PredicateMain {
data_section: DataSection,
program_section: InstructionSet,
},
Library,
}
impl FinalizedAsm {
pub(crate) fn to_bytecode_mut(&mut self) -> CompileResult<Vec<u8>> {
use FinalizedAsm::*;
match self {
ContractAbi {
program_section,
ref mut data_section,
} => to_bytecode_mut(program_section, data_section),
Library => ok(vec![], vec![], vec![]),
ScriptMain {
program_section,
ref mut data_section,
} => to_bytecode_mut(program_section, data_section),
PredicateMain {
program_section,
ref mut data_section,
} => to_bytecode_mut(program_section, data_section),
}
}
}
fn to_bytecode_mut(
program_section: &InstructionSet,
data_section: &mut DataSection,
) -> CompileResult<Vec<u8>> {
let mut errors = vec![];
if program_section.ops.len() & 1 != 0 {
println!("ops len: {}", program_section.ops.len());
errors.push(CompileError::Internal(
"Non-word-aligned (odd-number) ops generated. This is an invariant violation.",
Span {
span: pest::Span::new(" ".into(), 0, 0).unwrap(),
path: None,
},
));
return err(vec![], errors);
}
assert_eq!(program_section.ops.len() & 1, 0);
let offset_to_data_section_in_bytes =
program_section
.ops
.iter()
.fold(0, |acc, item| match &item.opcode {
AllocatedOpcode::LWDataId(_reg, data_label)
if data_section
.type_of_data(data_label)
.expect("data label references non existent data -- internal error")
.stack_size_of()
> 1 =>
{
acc + 8
}
_ => acc + 4,
})
+ 4;
let mut buf = vec![0; (program_section.ops.len() * 4) + 4];
let mut half_word_ix = 0;
for op in program_section.ops.iter() {
let op = op.to_fuel_asm(offset_to_data_section_in_bytes, data_section);
match op {
Either::Right(data) => {
for i in 0..data.len() {
buf[(half_word_ix * 4) + i] = data[i];
}
half_word_ix += 2;
}
Either::Left(ops) => {
if ops.len() > 1 {
buf.resize(buf.len() + ((ops.len() - 1) * 4), 0);
}
for mut op in ops {
op.read_exact(&mut buf[half_word_ix * 4..])
.expect("Failed to write to in-memory buffer.");
half_word_ix += 1;
}
}
}
}
let mut data_section = data_section.serialize_to_bytes();
buf.append(&mut data_section);
ok(buf, vec![], errors)
}