Skip to content

Commit 59c566f

Browse files
authored
Do not allow inline VirtualImmediate* instantiations (#6852)
Fixes #6811
1 parent 7aa59f9 commit 59c566f

11 files changed

+256
-192
lines changed

sway-core/src/asm_generation/finalized_asm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ fn to_bytecode_mut(
136136
}
137137
AllocatedOpcode::ConfigurablesOffsetPlaceholder => 8,
138138
AllocatedOpcode::DataSectionOffsetPlaceholder => 8,
139-
AllocatedOpcode::BLOB(count) => count.value as u64 * 4,
140-
AllocatedOpcode::CFEI(i) | AllocatedOpcode::CFSI(i) if i.value == 0 => 0,
139+
AllocatedOpcode::BLOB(count) => count.value() as u64 * 4,
140+
AllocatedOpcode::CFEI(i) | AllocatedOpcode::CFSI(i) if i.value() == 0 => 0,
141141
_ => 4,
142142
}
143143
}

sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl AllocatedAbstractInstructionSet {
5050
let remove = match &op.opcode {
5151
// `cfei i0` and `cfsi i0` pairs.
5252
Either::Left(AllocatedOpcode::CFEI(imm))
53-
| Either::Left(AllocatedOpcode::CFSI(imm)) => imm.value == 0u32,
53+
| Either::Left(AllocatedOpcode::CFSI(imm)) => imm.value() == 0u32,
5454
// `cfe $zero` and `cfs $zero` pairs.
5555
Either::Left(AllocatedOpcode::CFE(reg))
5656
| Either::Left(AllocatedOpcode::CFS(reg)) => reg.is_zero(),
@@ -145,14 +145,14 @@ impl AllocatedAbstractInstructionSet {
145145
.collect::<Vec<_>>();
146146

147147
let (mask_l, mask_h) = generate_mask(&regs);
148-
if mask_l.value != 0 {
148+
if mask_l.value() != 0 {
149149
new_ops.push(AllocatedAbstractOp {
150150
opcode: Either::Left(AllocatedOpcode::PSHL(mask_l)),
151151
comment: "save registers 16..40".into(),
152152
owning_span: op.owning_span.clone(),
153153
});
154154
}
155-
if mask_h.value != 0 {
155+
if mask_h.value() != 0 {
156156
new_ops.push(AllocatedAbstractOp {
157157
opcode: Either::Left(AllocatedOpcode::PSHH(mask_h)),
158158
comment: "save registers 40..64".into(),
@@ -171,14 +171,14 @@ impl AllocatedAbstractInstructionSet {
171171
.collect::<Vec<_>>();
172172

173173
let (mask_l, mask_h) = generate_mask(&regs);
174-
if mask_h.value != 0 {
174+
if mask_h.value() != 0 {
175175
new_ops.push(AllocatedAbstractOp {
176176
opcode: Either::Left(AllocatedOpcode::POPH(mask_h)),
177177
comment: "restore registers 40..64".into(),
178178
owning_span: op.owning_span.clone(),
179179
});
180180
}
181-
if mask_l.value != 0 {
181+
if mask_l.value() != 0 {
182182
new_ops.push(AllocatedAbstractOp {
183183
opcode: Either::Left(AllocatedOpcode::POPL(mask_l)),
184184
comment: "restore registers 16..40".into(),
@@ -334,7 +334,7 @@ impl AllocatedAbstractInstructionSet {
334334
opcode: AllocatedOpcode::SRLI(
335335
r1.clone(),
336336
r1.clone(),
337-
VirtualImmediate12 { value: 2 },
337+
VirtualImmediate12::new_unchecked(2, "two must fit in 12 bits"),
338338
),
339339
owning_span: owning_span.clone(),
340340
comment: "get current instruction offset in 32-bit words".into(),
@@ -469,13 +469,13 @@ impl AllocatedAbstractInstructionSet {
469469
// cfei 0 and cfsi 0 are omitted from asm emission, don't count them for offsets
470470
Either::Left(AllocatedOpcode::CFEI(ref op))
471471
| Either::Left(AllocatedOpcode::CFSI(ref op))
472-
if op.value == 0 =>
472+
if op.value() == 0 =>
473473
{
474474
0
475475
}
476476

477477
// Another special case for the blob opcode, used for testing.
478-
Either::Left(AllocatedOpcode::BLOB(ref count)) => count.value as u64,
478+
Either::Left(AllocatedOpcode::BLOB(ref count)) => count.value() as u64,
479479

480480
// These ops will end up being exactly one op, so the cur_offset goes up one.
481481
Either::Right(Jump(..) | JumpIfNotZero(..) | Call(..) | LoadLabel(..))
@@ -612,15 +612,15 @@ impl AllocatedAbstractInstructionSet {
612612
new_ops.push(AllocatedAbstractOp {
613613
opcode: Either::Left(AllocatedOpcode::JMPB(
614614
AllocatedRegister::Constant(ConstantRegister::Scratch),
615-
VirtualImmediate18 { value: 0 },
615+
VirtualImmediate18::new_unchecked(0, "zero must fit in 18 bits"),
616616
)),
617617
..op
618618
});
619619
} else {
620620
new_ops.push(AllocatedAbstractOp {
621621
opcode: Either::Left(AllocatedOpcode::JMPF(
622622
AllocatedRegister::Constant(ConstantRegister::Scratch),
623-
VirtualImmediate18 { value: 0 },
623+
VirtualImmediate18 ::new_unchecked(0, "zero must fit in 18 bits"),
624624
)),
625625
..op
626626
});
@@ -656,7 +656,7 @@ impl AllocatedAbstractInstructionSet {
656656
opcode: Either::Left(AllocatedOpcode::JNZB(
657657
r1.clone(),
658658
AllocatedRegister::Constant(ConstantRegister::Scratch),
659-
VirtualImmediate12 { value: 0 },
659+
VirtualImmediate12::new_unchecked(0, "zero must fit in 12 bits"),
660660
)),
661661
..op
662662
});
@@ -665,7 +665,7 @@ impl AllocatedAbstractInstructionSet {
665665
opcode: Either::Left(AllocatedOpcode::JNZF(
666666
r1.clone(),
667667
AllocatedRegister::Constant(ConstantRegister::Scratch),
668-
VirtualImmediate12 { value: 0 },
668+
VirtualImmediate12::new_unchecked(0, "zero must fit in 12 bits"),
669669
)),
670670
..op
671671
});

sway-core/src/asm_generation/fuel/checks.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ use sway_error::{
77
};
88
use sway_types::Span;
99

10-
use crate::asm_lang::{
11-
allocated_ops::{AllocatedOp, AllocatedOpcode},
12-
VirtualImmediate18,
13-
};
10+
use crate::asm_lang::allocated_ops::{AllocatedOp, AllocatedOpcode};
1411

1512
/// Checks if an opcode is one that cannot be executed from within a script.
1613
/// If so, throw an error.
@@ -31,8 +28,8 @@ pub(crate) fn check_script_opcodes(
3128
// Preemptively avoids the creation of scripts with opcodes not allowed at runtime.
3229
handler.scope(|handler| {
3330
for op in ops {
34-
match op.opcode {
35-
GM(_, VirtualImmediate18 { value: 1..=2 }) => {
31+
match &op.opcode {
32+
GM(_, imm) if (1..=2).contains(&imm.value()) => {
3633
handler.emit_err(CompileError::GMFromExternalContext {
3734
span: get_op_span(op),
3835
});
@@ -102,7 +99,7 @@ pub(crate) fn check_predicate_opcodes(
10299
CCP(..) => invalid_opcode("CCP"),
103100
CROO(..) => invalid_opcode("CROO"),
104101
CSIZ(..) => invalid_opcode("CSIZ"),
105-
GM(_, VirtualImmediate18 { value: 1..=2 }) => {
102+
GM(_, imm) if (1..=2).contains(&imm.value()) => {
106103
handler.emit_err(CompileError::GMFromExternalContext {
107104
span: get_op_span(op),
108105
});

sway-core/src/asm_generation/fuel/fuel_asm_builder.rs

+35-27
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ impl AsmBuilder for FuelAsmBuilder<'_, '_> {
141141
opcode: Either::Left(VirtualOp::ADDI(
142142
VirtualRegister::Constant(ConstantRegister::FuncArg1),
143143
VirtualRegister::Constant(ConstantRegister::Zero),
144-
VirtualImmediate12 {
145-
value: encoded_bytes.len() as u16,
146-
},
144+
VirtualImmediate12::new_unchecked(
145+
encoded_bytes.len() as u64,
146+
"Error representing encoded_bytes length as 12-bit immediate",
147+
),
147148
)),
148149
comment: format!("get length of configurable {} default value", name),
149150
owning_span: None,
@@ -153,9 +154,10 @@ impl AsmBuilder for FuelAsmBuilder<'_, '_> {
153154
opcode: Either::Left(VirtualOp::ADDI(
154155
VirtualRegister::Constant(ConstantRegister::FuncArg2),
155156
VirtualRegister::Constant(ConstantRegister::StackStartPointer),
156-
VirtualImmediate12 {
157-
value: global.offset_in_bytes as u16,
158-
},
157+
VirtualImmediate12::new_unchecked(
158+
global.offset_in_bytes,
159+
"Error representing global offset as 12-bit immediate",
160+
),
159161
)),
160162
comment: format!("get pointer to configurable {} stack address", name),
161163
owning_span: None,
@@ -698,7 +700,10 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
698700
opcode: Either::Left(VirtualOp::XORI(
699701
res_reg.clone(),
700702
res_reg.clone(),
701-
VirtualImmediate12 { value: 1 },
703+
VirtualImmediate12::new_unchecked(
704+
1,
705+
"Error representing 1 as 12-bit immediate",
706+
),
702707
)),
703708
comment: "[bitcast to bool]: invert inverted boolean".into(),
704709
owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
@@ -1278,7 +1283,10 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
12781283
opcode: Either::Left(VirtualOp::MULI(
12791284
instr_reg.clone(),
12801285
instr_reg.clone(),
1281-
VirtualImmediate12 { value: 8u16 },
1286+
VirtualImmediate12::new_unchecked(
1287+
8,
1288+
"Error representing 8 as 12-bit immediate",
1289+
),
12821290
)),
12831291
comment: "get byte offset to local from base".into(),
12841292
owning_span: owning_span.clone(),
@@ -1345,9 +1353,10 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
13451353
opcode: either::Either::Left(VirtualOp::ADDI(
13461354
addr_reg.clone(),
13471355
VirtualRegister::Constant(ConstantRegister::StackStartPointer),
1348-
VirtualImmediate12 {
1349-
value: g.offset_in_bytes as u16,
1350-
},
1356+
VirtualImmediate12::new_unchecked(
1357+
g.offset_in_bytes,
1358+
"offset must fit in 12 bits",
1359+
),
13511360
)),
13521361
comment: format!("get address of configurable {}", name),
13531362
owning_span: self.md_mgr.val_to_span(self.context, *addr_val),
@@ -1382,9 +1391,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
13821391
opcode: either::Either::Left(VirtualOp::GTF(
13831392
instr_reg.clone(),
13841393
index_reg,
1385-
VirtualImmediate12 {
1386-
value: tx_field_id as u16,
1387-
},
1394+
VirtualImmediate12::new_unchecked(tx_field_id, "tx_field_id must fit in 12 bits"),
13881395
)),
13891396
comment: "get transaction field".into(),
13901397
owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
@@ -1416,7 +1423,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
14161423
opcode: Either::Left(VirtualOp::LB(
14171424
instr_reg.clone(),
14181425
src_reg,
1419-
VirtualImmediate12 { value: 0 },
1426+
VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"),
14201427
)),
14211428
comment: "load byte".into(),
14221429
owning_span,
@@ -1427,7 +1434,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
14271434
opcode: Either::Left(VirtualOp::LW(
14281435
instr_reg.clone(),
14291436
src_reg,
1430-
VirtualImmediate12 { value: 0 },
1437+
VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"),
14311438
)),
14321439
comment: "load word".into(),
14331440
owning_span,
@@ -1479,9 +1486,10 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
14791486
self.cur_bytecode.push(Op {
14801487
opcode: Either::Left(VirtualOp::MOVI(
14811488
len_reg.clone(),
1482-
VirtualImmediate18 {
1483-
value: byte_len as u32,
1484-
},
1489+
VirtualImmediate18::new_unchecked(
1490+
byte_len,
1491+
"cannot fit byte length in 18 bits",
1492+
),
14851493
)),
14861494
comment: "get data length for memory copy".into(),
14871495
owning_span: owning_span.clone(),
@@ -1555,7 +1563,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
15551563
opcode: Either::Left(VirtualOp::LW(
15561564
ptr_reg.clone(),
15571565
log_val_reg.clone(),
1558-
VirtualImmediate12 { value: 0 },
1566+
VirtualImmediate12::new_unchecked(0, "zero must fit in 12 bits"),
15591567
)),
15601568
owning_span: owning_span.clone(),
15611569
comment: "load slice pointer for logging data".into(),
@@ -1564,7 +1572,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
15641572
opcode: Either::Left(VirtualOp::LW(
15651573
size_reg.clone(),
15661574
log_val_reg.clone(),
1567-
VirtualImmediate12 { value: 1 },
1575+
VirtualImmediate12::new_unchecked(1, "one must fit in 12 bits"),
15681576
)),
15691577
owning_span: owning_span.clone(),
15701578
comment: "load slice size for logging data".into(),
@@ -1675,7 +1683,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
16751683
opcode: Either::Left(VirtualOp::LW(
16761684
size_reg.clone(),
16771685
ret_reg.clone(),
1678-
VirtualImmediate12 { value: 1 },
1686+
VirtualImmediate12::new_unchecked(1, "one must fit in 12 bits"),
16791687
)),
16801688
owning_span: owning_span.clone(),
16811689
comment: "load size of returned slice".into(),
@@ -1684,7 +1692,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
16841692
opcode: Either::Left(VirtualOp::LW(
16851693
ret_reg.clone(),
16861694
ret_reg.clone(),
1687-
VirtualImmediate12 { value: 0 },
1695+
VirtualImmediate12::new_unchecked(0, "zero must fit in 12 bits"),
16881696
)),
16891697
owning_span: owning_span.clone(),
16901698
comment: "load pointer to returned slice".into(),
@@ -2004,7 +2012,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
20042012
opcode: Either::Left(VirtualOp::SB(
20052013
dst_reg,
20062014
val_reg,
2007-
VirtualImmediate12 { value: 0 },
2015+
VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"),
20082016
)),
20092017
comment: "store byte".into(),
20102018
owning_span,
@@ -2015,7 +2023,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
20152023
opcode: Either::Left(VirtualOp::SW(
20162024
dst_reg,
20172025
val_reg,
2018-
VirtualImmediate12 { value: 0 },
2026+
VirtualImmediate12::new_unchecked(0, "Zero must fit in 12 bits"),
20192027
)),
20202028
comment: "store word".into(),
20212029
owning_span,
@@ -2179,7 +2187,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
21792187
reg,
21802188
#[allow(clippy::unnecessary_unwrap)]
21812189
base.unwrap().clone(),
2182-
VirtualImmediate12 { value: imm as u16 },
2190+
VirtualImmediate12::new_unchecked(imm, "immediate must fit in 12 bits"),
21832191
)),
21842192
comment: comment.into(),
21852193
owning_span: span,
@@ -2189,7 +2197,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
21892197
self.cur_bytecode.push(Op {
21902198
opcode: Either::Left(VirtualOp::MOVI(
21912199
reg.clone(),
2192-
VirtualImmediate18 { value: imm as u32 },
2200+
VirtualImmediate18::new_unchecked(imm, "immediate must fit in 12 bits"),
21932201
)),
21942202
comment: comment.clone(),
21952203
owning_span: span.clone(),

0 commit comments

Comments
 (0)