Skip to content

Commit

Permalink
match for string slices (#6202)
Browse files Browse the repository at this point in the history
## Description

This PR implements `match` for string slices including radix trie
optimization and is a task of
#5110.

For example a simple `match` like 

```
fn return_match_on_str_slice(param: str) -> u64 {
    match param {
        "get_a" => { 1u64 },
        "get_a_b" => { 2u64 },
        "get_b" => { 3u64 },
        _ => { 1000u64 },
    }
}
``` 

will generate code following this logic:

```
     let packed_string = "get_a_b"
     if str.len() == 5
         if str[0..4] == "get_" at packed_string[0]
             if str[4..5] == "b" at packed_string[6]
                 return branch 2
             if str[4..5] == "a" at packed_string[4]
                 return branch 0
             return wildcard branch
         return wildcard branch
     if str.len() == 7
         if str[0..7] == "get_a_b" at packed_string[0]
             return branch 1
         return wildcard branch
     return wildcard branch
```

In logical terms, this boils down to checking the length and an `O(N)`
check on the string. Albeit the bytecode will be more complex because of
all the branches.

Another interesting optimization is the "packed string literal" that
coalesces all "match arms string slices" into just one string. In the
case above, given that one of the arms contains all the necessary
strings for all other comparisons, we will create just one string
literal. Saving a lot of bytes in the data section.

The section below describes how `rustc` deals with this desugaring. I
think these choices make more sense to us for two reasons:

1 - Avoid testing common prefixes multiple times will spend less gas in
general (needs more testing);
2 - packing all strings will decrease the data section size.

This is the bytecode generated in this case:

```
fn return_match_on_str_slice(param: str) -> u64 {
              match param {
                  "get_a" => { 1u64 },
                  "get_a_b" => { 2u64 },
                  "get_b" => { 3u64 },
                  _ => { 1000u64 },
              }
          } @ /home/xunilrj/github/sway/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all/src/main.sw:22:1
              0x0000017c PSHL 0xf                                        ;; [149, 0, 0, 15]
              0x00000180 PSHH 0x80000                                    ;; [150, 8, 0, 0]
              0x00000184 MOVE R59 $sp                                    ;; [26, 236, 80, 0]
              0x00000188 CFEI 0x90                                       ;; [145, 0, 0, 144]
              0x0000018c MOVE $writable R58                              ;; [26, 67, 160, 0]
              0x00000190 MOVE R19 R62                                    ;; [26, 79, 224, 0]
          match param {
                  "get_a" => { 1u64 },
                  "get_a_b" => { 2u64 },
                  "get_b" => { 3u64 },
                  _ => { 1000u64 },
              } @ /home/xunilrj/github/sway/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all/src/main.sw:23:5
              0x00000194 ADDI R17 R59 0x80                               ;; 
              0x00000198 MOVI R18 0x10                                   ;; 
              0x0000019c MCP R17 $writable R18                           ;; 
              0x000001a0 MOVI R17 0x7                                    ;; 0x7 = "get_a_b".len()
           @ <autogenerated>:1:1
              0x000001a4 LW $writable R59 0x11                           ;; R59 + 0x11 = a.len()
              0x000001a8 EQ $writable $writable R17                      ;; a.len() == 0x7
              0x000001ac JNZF $writable $zero 0x3c                       ;; if false jump to 2a0?
              
              0x000001b0 MOVI R17 0x5                                    ;; we have two arms with length equals 0x5
              0x000001b4 LW $writable R59 0x11                           ;; R59 + 0x11 = a.len()
              0x000001b8 EQ $writable $writable R17                      ;; a.len() == 0x5
              0x000001bc MOVI R17 0x3e8                                  ;; 0x3e8 = 1000 (wildcard return value)
              0x000001c0 JNZF $writable $zero 0x1                        ;; if true jump to 1c8
              0x000001c4 JMPF $zero 0x35                                 ;; if false jump to 29c (will return R17)

              0x000001c8 LW $writable R63 0x3                            ;; R63 = start of data section, will load 13c
              0x000001cc ADD $writable $writable $pc                     ;; $writable = 0x308 = packed strings
              0x000001d0 ADDI R17 R59 0x20                               ;; 
              0x000001d4 SW R59 $writable 0x4                            ;; R59 + 0x4 = packed strings
              0x000001d8 MOVI $writable 0x7                              ;; 
              0x000001dc SW R59 $writable 0x5                            ;; R59 + 0x5 = 0x7
              0x000001e0 ADDI $writable R59 0x30                         ;; 
              0x000001e4 MOVI R18 0x10                                   ;; 
              0x000001e8 MCP $writable R17 R18                           ;; R59 + 0x30 = R59 + 0x20
              0x000001ec MOVI R18 0x4                                    ;; 0x4 = "get_".len()
              0x000001f0 LW $writable R59 0x10                           ;; 
              0x000001f4 ADDI $writable $writable 0x0                    ;; 
              0x000001f8 LW R17 R59 0x6                                  ;; R17 = a.ptr()
              0x000001fc ADDI R17 R17 0x0                                ;; 
              0x00000200 MEQ $writable $writable R17 R18                 ;; a[0..4] = packed[0..4]
              0x00000204 MOVI R17 0x3e8                                  ;; 0x3e8 = 1000 (wildcard return value)
              0x00000208 JNZF $writable $zero 0x1                        ;; if true jump to 210
              0x0000020c JMPF $zero 0x23                                 ;; if false jump to 29c (will return R17)
              ....      
          .data_section:
              0x00000300 .bytes as hex ([]), len i0, as ascii ""
              0x00000300 .word i18446744073709486084, as hex be bytes ([FF, FF, FF, FF, FF, FF, 00, 04])
              0x00000308 .bytes as hex ([67, 65, 74, 5F, 61, 5F, 62]), len i7, as ascii "get_a_b"
              0x00000310 .word i500, as hex be bytes ([00, 00, 00, 00, 00, 00, 01, F4])
              0x00000318 .word i316, as hex be bytes ([00, 00, 00, 00, 00, 00, 01, 3C])
              0x00000320 .word i244, as hex be bytes ([00, 00, 00, 00, 00, 00, 00, F4])
              0x00000328 .word i176, as hex be bytes ([00, 00, 00, 00, 00, 00, 00, B0])
              0x00000330 .word i100, as hex be bytes ([00, 00, 00, 00, 00, 00, 00, 64])
```

## How `rustc` desugar `match`

For comparison, this is the generated ASM with comments on how Rust
tackles this.
First, this is the function used:

```
#[inline(never)]
fn f(a: &str) -> u64 {
    match a {
        "get_method" => 0,
        "get_tokens" => 1,
        "get_something_else" => 2,
        "get_tokens_2" => 3,
        "clear" => 4,
        "get_m" => 5,
        _ => 6,
    }
}
``` 

This is the LLVM IR generated. There is a match on the length of each
string slice arms. The valid range is (5, 18), everything outside of
this is the wildcard match arm. This range will be important later.

```
efine internal fastcc noundef i64 @example::f::hdb860bcd6d383112(ptr noalias nocapture noundef nonnull readonly align 1 %a.0, i64 noundef %a.1) unnamed_addr {
start:
  switch i64 %a.1, label %bb13 [
    i64 10, label %"_ZN73_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..cmp..SlicePartialEq$LT$B$GT$$GT$5equal17h510120b4d3581de7E.exit"
    i64 18, label %"_ZN73_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..cmp..SlicePartialEq$LT$B$GT$$GT$5equal17h510120b4d3581de7E.exit30"
    i64 12, label %"_ZN73_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..cmp..SlicePartialEq$LT$B$GT$$GT$5equal17h510120b4d3581de7E.exit35"
    i64 5, label %"_ZN73_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..cmp..SlicePartialEq$LT$B$GT$$GT$5equal17h510120b4d3581de7E.exit40"
  ]
```
this is how "f" is called

```
	mov	rbx, qword ptr [rsp + 32]
	mov	r14, qword ptr [rsp + 40]
	mov	rsi, qword ptr [rsp + 48]     <- length of the string slice
	mov	rdi, r14                      <- ptr to string slice
	call	_ZN4main1f17h126a5dfd4e318ebcE
```

this is `f` body. 

`ja .LBB8_12` jumps into a simple return, returning EAX as 6. It is the
wildcard return value. The cleverness of this is that when `RSI` is
smaller than 5, it will become negative (because of `add rsi, -5`,
wrapping into huge unsigned ints, and will also trigger `JA` (which
stands for `Jump Above`), effectively jumping when the slice length is
outside of the expected range which is (5, 18).

After that, it uses a jump table based on the string length minus 5.
Everywhere the string length is invalid, the jump address is `LBB8_12`.,
still returning `EAX` as 6.

```
_ZN4main1f17h126a5dfd4e318ebcE:
	.cfi_startproc
	mov	eax, 6
	add	rsi, -5
	cmp	rsi, 13
	ja	.LBB8_12

	lea	rcx, [rip + .LJTI8_0]
	movsxd	rdx, dword ptr [rcx + 4*rsi]
	add	rdx, rcx
	jmp	rdx
```

```
.LBB8_12:
	ret
```

This is the jump table used:

```
.LJTI8_0:
	.long	.LBB8_9-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_2-.LJTI8_0        <- 5th entry is length = 10 (remember we add -5 to the length)
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_8-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_12-.LJTI8_0
	.long	.LBB8_6-.LJTI8_0
```

The interesting entry is entry 5, which has two strings: "get_method"
and "get_tokens". Here we can see that `rust` actually compares the
complete string slice twice. Even though they have an intersection.

```
.LBB8_2:
	movabs	rcx, 7526752397670245735=6874656D5F746567="htem_teg" (inverted "get_meth")
	xor	rcx, qword ptr [rdi]
	movzx	edx, word ptr [rdi + 8]
	xor	rdx, 25711=646F="do" (inverted "od")
	or	rdx, rcx
	je	.LBB8_3
	movabs	rcx, 7308057365947114855=656B6F745F746567="ekot_teg" (inverted "get_toke")
	xor	rcx, qword ptr [rdi]
	movzx	edx, word ptr [rdi + 8]
	xor	rdx, 29550=736E="sn" (inverted "ns")
	or	rdx, rcx
	je	.LBB8_5
```

```
.LBB8_3:
	xor	eax, eax    <- returns 0
	ret
```

```
.LBB8_5:
	mov	eax, 1     <- returns 1
	ret
```

This is comparable to what `clang` is doing:
rust-lang/rust#61961

## Code and Bytecode

This PR also implements code printing when printing bytecode. For now
this is only enable for tests. It gnerates something like:

```
  match param {
                  "get_a" => { 1u64 },
                  "get_a_b" => { 2u64 },
                  "get_b" => { 3u64 },
                  _ => { 1000u64 },
              } @ /home/xunilrj/github/sway/test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all/src/main.sw:23:5
              0x00000194 ADDI R17 R59 0x80                               ;; 
              0x00000198 MOVI R18 0x10                                   ;; 
              0x0000019c MCP R17 $writable R18                           ;; 
              0x000001a0 MOVI R17 0x7                                    ;; 0x7 = "get_a_b".len()
           @ <autogenerated>:1:1
              0x000001a4 LW $writable R59 0x11                           ;; R59 + 0x11 = a.len()
              0x000001a8 EQ $writable $writable R17                      ;; a.len() == 0x7  
```

As we can see, not great, but helpful nonetheless. We can (should?)
improve this by better "carrying" spans in all transformations and
lowerings.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [ ] I have added tests that prove my fix is effective or that my
feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [ ] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
Co-authored-by: IGI-111 <igi-111@protonmail.com>
  • Loading branch information
3 people committed Jul 5, 2024
1 parent 00a9254 commit bcd1cf9
Show file tree
Hide file tree
Showing 26 changed files with 805 additions and 73 deletions.
5 changes: 5 additions & 0 deletions forc-pkg/src/manifest/build_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub struct BuildProfile {
#[serde(default)]
pub print_bytecode: bool,
#[serde(default)]
pub print_bytecode_spans: bool,
#[serde(default)]
pub terse: bool,
#[serde(default)]
pub time_phases: bool,
Expand Down Expand Up @@ -57,6 +59,7 @@ impl BuildProfile {
print_ir: PrintIr::default(),
print_asm: PrintAsm::default(),
print_bytecode: false,
print_bytecode_spans: false,
terse: false,
time_phases: false,
metrics_outfile: None,
Expand All @@ -80,6 +83,7 @@ impl BuildProfile {
print_ir: PrintIr::default(),
print_asm: PrintAsm::default(),
print_bytecode: false,
print_bytecode_spans: false,
terse: false,
time_phases: false,
metrics_outfile: None,
Expand Down Expand Up @@ -152,6 +156,7 @@ mod tests {
print_ir: PrintIr::r#final(),
print_asm: PrintAsm::all(),
print_bytecode: true,
print_bytecode_spans: false,
terse: true,
time_phases: true,
metrics_outfile: Some("metrics_outfile".into()),
Expand Down
8 changes: 7 additions & 1 deletion forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ pub struct PrintOpts {
pub asm: PrintAsm,
/// Print the bytecode. This is the final output of the compiler.
pub bytecode: bool,
/// Print the original source code together with bytecode.
pub bytecode_spans: bool,
/// Print the generated Sway IR (Intermediate Representation).
pub ir: PrintIr,
/// Output build errors and warnings in reverse order.
Expand Down Expand Up @@ -1557,7 +1559,10 @@ pub fn sway_build_config(
.with_print_dca_graph(build_profile.print_dca_graph.clone())
.with_print_dca_graph_url_format(build_profile.print_dca_graph_url_format.clone())
.with_print_asm(build_profile.print_asm)
.with_print_bytecode(build_profile.print_bytecode)
.with_print_bytecode(
build_profile.print_bytecode,
build_profile.print_bytecode_spans,
)
.with_print_ir(build_profile.print_ir.clone())
.with_include_tests(build_profile.include_tests)
.with_time_phases(build_profile.time_phases)
Expand Down Expand Up @@ -2087,6 +2092,7 @@ fn build_profile_from_opts(
profile.print_ir |= print.ir.clone();
profile.print_asm |= print.asm;
profile.print_bytecode |= print.bytecode;
profile.print_bytecode_spans |= print.bytecode_spans;
profile.terse |= pkg.terse;
profile.time_phases |= time_phases;
if profile.metrics_outfile.is_none() {
Expand Down
1 change: 1 addition & 0 deletions forc-plugins/forc-client/src/op/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ fn build_opts_from_cmd(cmd: &cmd::Deploy) -> pkg::BuildOpts {
dca_graph_url_format: cmd.print.dca_graph_url_format.clone(),
asm: cmd.print.asm(),
bytecode: cmd.print.bytecode,
bytecode_spans: false,
ir: cmd.print.ir(),
reverse_order: cmd.print.reverse_order,
},
Expand Down
1 change: 1 addition & 0 deletions forc-plugins/forc-client/src/op/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ fn build_opts_from_cmd(cmd: &cmd::Run) -> pkg::BuildOpts {
dca_graph_url_format: cmd.print.dca_graph_url_format.clone(),
asm: cmd.print.asm(),
bytecode: cmd.print.bytecode,
bytecode_spans: false,
ir: cmd.print.ir(),
reverse_order: cmd.print.reverse_order,
},
Expand Down
1 change: 1 addition & 0 deletions forc/src/cli/commands/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ fn opts_from_cmd(cmd: Command) -> forc_test::TestOpts {
dca_graph_url_format: cmd.build.print.dca_graph_url_format.clone(),
asm: cmd.build.print.asm(),
bytecode: cmd.build.print.bytecode,
bytecode_spans: false,
ir: cmd.build.print.ir(),
reverse_order: cmd.build.print.reverse_order,
},
Expand Down
1 change: 1 addition & 0 deletions forc/src/ops/forc_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ fn opts_from_cmd(cmd: BuildCommand) -> pkg::BuildOpts {
dca_graph_url_format: cmd.build.print.dca_graph_url_format.clone(),
asm: cmd.build.print.asm(),
bytecode: cmd.build.print.bytecode,
bytecode_spans: false,
ir: cmd.build.print.ir(),
reverse_order: cmd.build.print.reverse_order,
},
Expand Down
1 change: 1 addition & 0 deletions forc/src/ops/forc_contract_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fn build_opts_from_cmd(cmd: &ContractIdCommand) -> pkg::BuildOpts {
dca_graph_url_format: cmd.print.dca_graph_url_format.clone(),
asm: cmd.print.asm(),
bytecode: cmd.print.bytecode,
bytecode_spans: false,
ir: cmd.print.ir(),
reverse_order: cmd.print.reverse_order,
},
Expand Down
1 change: 1 addition & 0 deletions forc/src/ops/forc_predicate_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fn build_opts_from_cmd(cmd: PredicateRootCommand) -> pkg::BuildOpts {
dca_graph_url_format: cmd.print.dca_graph_url_format.clone(),
asm: cmd.print.asm(),
bytecode: cmd.print.bytecode,
bytecode_spans: false,
ir: cmd.print.ir(),
reverse_order: cmd.print.reverse_order,
},
Expand Down
107 changes: 104 additions & 3 deletions sway-core/src/asm_generation/finalized_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::{
fuel::{checks, data_section::DataSection},
ProgramABI, ProgramKind,
};
use crate::asm_generation::fuel::data_section::{DataId, Datum, Entry};
use crate::asm_lang::allocated_ops::{AllocatedOp, AllocatedOpcode};
use crate::decl_engine::DeclRefFunction;
use crate::source_map::SourceMap;
Expand Down Expand Up @@ -151,6 +152,13 @@ fn to_bytecode_mut(
println!(";; --- START OF TARGET BYTECODE ---\n");
}

let mut last_span = None;
let mut indentation = if build_config.print_bytecode_spans {
4
} else {
0
};

let mut half_word_ix = 0;
let mut offset_from_instr_start = 0;
for op in ops.iter() {
Expand All @@ -165,7 +173,7 @@ fn to_bytecode_mut(
match fuel_op {
Either::Right(data) => {
if build_config.print_bytecode {
print!("{:#010x} ", bytecode.len());
print!("{}{:#010x} ", " ".repeat(indentation), bytecode.len());
println!(
" ;; {:?}",
data
Expand All @@ -181,8 +189,45 @@ fn to_bytecode_mut(
}
Either::Left(instructions) => {
for instruction in instructions {
// Print original source span only once
if build_config.print_bytecode_spans {
last_span = match (last_span, &span) {
(None, Some(span)) => {
indentation = 4;
let line_col = span.start_pos().line_col();
println!(
"{} @ {}:{}:{}",
span.as_str(),
span.source_id()
.map(|source_id| source_engine.get_path(source_id))
.map(|x| x.display().to_string())
.unwrap_or("<autogenerated>".to_string()),
line_col.line,
line_col.col
);
Some(span.clone())
}
(Some(last), Some(span)) if last != *span => {
indentation = 4;
let line_col = span.start_pos().line_col();
println!(
"{} @ {}:{}:{}",
span.as_str(),
span.source_id()
.map(|source_id| source_engine.get_path(source_id))
.map(|x| x.display().to_string())
.unwrap_or("<autogenerated>".to_string()),
line_col.line,
line_col.col
);
Some(span.clone())
}
(last, _) => last,
};
}

if build_config.print_bytecode {
print!("{:#010x} ", bytecode.len());
print!("{}{:#010x} ", " ".repeat(indentation), bytecode.len());
print_instruction(&instruction);
}

Expand All @@ -202,8 +247,64 @@ fn to_bytecode_mut(
}
}
}

if build_config.print_bytecode {
println!("{}", data_section);
println!(".data_section:");

let offset = bytecode.len();

fn print_entry(indentation: usize, offset: usize, pair: &Entry) {
print!("{}{:#010x} ", " ".repeat(indentation), offset);

match &pair.value {
Datum::Byte(w) => println!(".byte i{w}, as hex {w:02X}"),
Datum::Word(w) => {
println!(".word i{w}, as hex be bytes ({:02X?})", w.to_be_bytes())
}
Datum::ByteArray(bs) => {
print!(".bytes as hex ({bs:02X?}), len i{}, as ascii \"", bs.len());

for b in bs {
print!(
"{}",
if *b == b' ' || b.is_ascii_graphic() {
*b as char
} else {
'.'
}
);
}
println!("\"");
}
Datum::Slice(bs) => {
print!(".slice as hex ({bs:02X?}), len i{}, as ascii \"", bs.len());

for b in bs {
print!(
"{}",
if *b == b' ' || b.is_ascii_graphic() {
*b as char
} else {
'.'
}
);
}
println!("\"");
}
Datum::Collection(els) => {
println!(".collection");
for e in els {
print_entry(indentation + 1, offset, e);
}
}
};
}

for (i, entry) in data_section.value_pairs.iter().enumerate() {
let entry_offset = data_section.data_id_to_offset(&DataId(i as u32));
print_entry(indentation, offset + entry_offset, entry);
}

println!(";; --- END OF TARGET BYTECODE ---\n");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ impl AllocatedAbstractInstructionSet {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::PSHL(mask_l)),
comment: "Save registers 16..40".into(),
owning_span: None,
owning_span: op.owning_span.clone(),
});
}
if mask_h.value != 0 {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::PSHH(mask_h)),
comment: "Save registers 40..64".into(),
owning_span: None,
owning_span: op.owning_span.clone(),
});
}
}
Expand All @@ -147,14 +147,14 @@ impl AllocatedAbstractInstructionSet {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::POPH(mask_h)),
comment: "Restore registers 40..64".into(),
owning_span: None,
owning_span: op.owning_span.clone(),
});
}
if mask_l.value != 0 {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::POPL(mask_l)),
comment: "Restore registers 16..40".into(),
owning_span: None,
owning_span: op.owning_span.clone(),
});
}
}
Expand Down
6 changes: 3 additions & 3 deletions sway-core/src/asm_generation/fuel/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
function.get_name(self.context)
);

self.cur_bytecode.push(match span {
Some(span) => Op::jump_label_comment(start_label, span, comment),
self.cur_bytecode.push(match &span {
Some(span) => Op::jump_label_comment(start_label, span.clone(), comment),
None => Op::unowned_jump_label_comment(start_label, comment),
});

Expand All @@ -285,7 +285,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
self.cur_bytecode.push(Op {
opcode: Either::Right(OrganizationalOp::PushAll(start_label)),
comment: "save all regs".to_owned(),
owning_span: None,
owning_span: span.clone(),
});
}

Expand Down
7 changes: 5 additions & 2 deletions sway-core/src/build_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub struct BuildConfig {
pub(crate) print_dca_graph_url_format: Option<String>,
pub(crate) print_asm: PrintAsm,
pub(crate) print_bytecode: bool,
pub(crate) print_bytecode_spans: bool,
pub(crate) print_ir: PrintIr,
pub(crate) include_tests: bool,
pub(crate) optimization_level: OptLevel,
Expand Down Expand Up @@ -234,6 +235,7 @@ impl BuildConfig {
print_dca_graph_url_format: None,
print_asm: PrintAsm::default(),
print_bytecode: false,
print_bytecode_spans: false,
print_ir: PrintIr::default(),
include_tests: false,
time_phases: false,
Expand Down Expand Up @@ -264,9 +266,10 @@ impl BuildConfig {
Self { print_asm, ..self }
}

pub fn with_print_bytecode(self, a: bool) -> Self {
pub fn with_print_bytecode(self, bytecode: bool, bytecode_spans: bool) -> Self {
Self {
print_bytecode: a,
print_bytecode: bytecode,
print_bytecode_spans: bytecode_spans,
..self
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ use super::{
///
/// # Details
///
/// This algorithm checks is a match expression is exhaustive and if its match
/// This algorithm checks if a match expression is exhaustive and if its match
/// arms are reachable by applying the above definitions of usefulness and
/// witnesses. This algorithm sequentially creates a [WitnessReport] for every
/// match arm by calling *U(P, q)*, where *P* is the [Matrix] of patterns seen
Expand Down
Loading

0 comments on commit bcd1cf9

Please sign in to comment.