Skip to content

Commit

Permalink
Merge branch 'master' into vaivaswatha/jmp_to_ssp
Browse files Browse the repository at this point in the history
  • Loading branch information
vaivaswatha authored Feb 16, 2024
2 parents 7c974c2 + 65c1927 commit c67a5da
Show file tree
Hide file tree
Showing 35 changed files with 417 additions and 262 deletions.
3 changes: 3 additions & 0 deletions forc-pkg/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ pub struct DependencyDetails {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct BuildProfile {
pub name: String,
#[serde(default)]
pub print_ast: bool,
pub print_dca_graph: Option<String>,
Expand Down Expand Up @@ -716,6 +717,7 @@ impl BuildProfile {

pub fn debug() -> Self {
Self {
name: Self::DEBUG.into(),
print_ast: false,
print_dca_graph: None,
print_dca_graph_url_format: None,
Expand All @@ -738,6 +740,7 @@ impl BuildProfile {

pub fn release() -> Self {
Self {
name: Self::RELEASE.to_string(),
print_ast: false,
print_dca_graph: None,
print_dca_graph_url_format: None,
Expand Down
74 changes: 44 additions & 30 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
source::{self, IPFSNode, Source},
};
use anyhow::{anyhow, bail, Context, Error, Result};
use forc_tracing::println_warning;
use forc_util::{
default_output_directory, find_file_name, kebab_to_snake_case, print_compiling,
print_on_failure, print_warnings,
Expand Down Expand Up @@ -50,7 +51,7 @@ use sway_error::{error::CompileError, handler::Handler, warning::CompileWarning}
use sway_types::constants::{CORE, PRELUDE, STD};
use sway_types::{Ident, Span, Spanned};
use sway_utils::{constants, time_expr, PerformanceData, PerformanceMetric};
use tracing::{info, warn};
use tracing::{debug, info, warn};

type GraphIx = u32;
type Node = Pinned;
Expand Down Expand Up @@ -492,7 +493,7 @@ impl BuiltPackage {
let json_abi_path = output_dir.join(program_abi_stem).with_extension("json");
self.write_json_abi(&json_abi_path, minify.clone())?;

info!(" Bytecode size: {} bytes", self.bytecode.bytes.len());
debug!(" Bytecode size: {} bytes", self.bytecode.bytes.len());
// Additional ops required depending on the program type
match self.tree_type {
TreeType::Contract => {
Expand Down Expand Up @@ -2036,52 +2037,50 @@ pub const SWAY_BIN_ROOT_SUFFIX: &str = "-bin-root";
fn build_profile_from_opts(
build_profiles: &HashMap<String, BuildProfile>,
build_options: &BuildOpts,
) -> Result<(String, BuildProfile)> {
) -> Result<BuildProfile> {
let BuildOpts {
pkg,
print,
time_phases,
build_profile,
release,
time_phases,
metrics_outfile,
tests,
error_on_warnings,
experimental,
..
} = build_options;
let mut selected_build_profile = BuildProfile::DEBUG;

match &build_profile {
Some(build_profile) => {
if *release {
warn!(
"You specified both {} and 'release' profiles. Using the 'release' profile",
let selected_profile_name = match &build_profile {
Some(build_profile) => match release {
true => {
println_warning(&format!(
"Both {} and 'release' profiles were specified. Using the 'release' profile",
build_profile
);
selected_build_profile = BuildProfile::RELEASE;
} else {
selected_build_profile = build_profile;
));
BuildProfile::RELEASE
}
}
None => {
if *release {
selected_build_profile = BuildProfile::RELEASE;
}
}
}
false => build_profile,
},
None => match release {
true => BuildProfile::RELEASE,
false => BuildProfile::DEBUG,
},
};

// Retrieve the specified build profile
let mut profile = build_profiles
.get(selected_build_profile)
.get(selected_profile_name)
.cloned()
.unwrap_or_else(|| {
warn!(
"provided profile option {} is not present in the manifest file. \
Using default profile.",
selected_build_profile
selected_profile_name
);
Default::default()
});
profile.name = selected_profile_name.into();
profile.print_ast |= print.ast;
if profile.print_dca_graph.is_none() {
profile.print_dca_graph = print.dca_graph.clone();
Expand All @@ -2102,7 +2101,18 @@ fn build_profile_from_opts(
profile.error_on_warnings |= error_on_warnings;
profile.experimental = experimental.clone();

Ok((selected_build_profile.to_string(), profile))
Ok(profile)
}

/// Returns a formatted string of the selected build profile and targets.
fn profile_target_string(profile_name: &str, build_target: &BuildTarget) -> String {
let mut targets = vec![format!("{build_target}")];
match profile_name {
BuildProfile::DEBUG => targets.insert(0, "unoptimized".into()),
BuildProfile::RELEASE => targets.insert(0, "optimized".into()),
_ => {}
};
format!("{profile_name} [{}] target(s)", targets.join(" + "))
}

/// Check if the given node is a contract dependency of any node in the graph.
Expand Down Expand Up @@ -2143,7 +2153,7 @@ pub fn build_with_options(build_options: BuildOpts) -> Result<Built> {
.find(|&pkg_manifest| pkg_manifest.dir() == path);
let build_profiles: HashMap<String, BuildProfile> = build_plan.build_profiles().collect();
// Get the selected build profile using build options
let (profile_name, build_profile) = build_profile_from_opts(&build_profiles, &build_options)?;
let build_profile = build_profile_from_opts(&build_profiles, &build_options)?;
// If this is a workspace we want to have all members in the output.
let outputs = match curr_manifest {
Some(pkg_manifest) => std::iter::once(
Expand All @@ -2164,16 +2174,20 @@ pub fn build_with_options(build_options: BuildOpts) -> Result<Built> {
let output_dir = pkg.output_directory.as_ref().map(PathBuf::from);

let finished = ansi_term::Colour::Green.bold().paint("Finished");
info!(" {finished} {profile_name} in {:?}", build_start.elapsed());
info!(
" {finished} {} in {:.2}s",
profile_target_string(&build_profile.name, build_target),
build_start.elapsed().as_secs_f32()
);
for (node_ix, built_package) in built_packages.into_iter() {
print_pkg_summary_header(&built_package);
let pinned = &graph[node_ix];
let pkg_manifest = manifest_map
.get(&pinned.id())
.ok_or_else(|| anyhow!("Couldn't find member manifest for {}", pinned.name))?;
let output_dir = output_dir
.clone()
.unwrap_or_else(|| default_output_directory(pkg_manifest.dir()).join(&profile_name));
let output_dir = output_dir.clone().unwrap_or_else(|| {
default_output_directory(pkg_manifest.dir()).join(&build_profile.name)
});
// Output artifacts for the built package
if let Some(outfile) = &binary_outfile {
built_package.write_bytecode(outfile.as_ref())?;
Expand Down Expand Up @@ -2208,7 +2222,7 @@ fn print_pkg_summary_header(built_pkg: &BuiltPackage) {
let name_ansi = ansi_term::Style::new()
.bold()
.paint(&built_pkg.descriptor.name);
info!("{padding}{ty_ansi} {name_ansi}");
debug!("{padding}{ty_ansi} {name_ansi}");
}

/// Returns the ContractId of a built_package contract with specified `salt`.
Expand Down
2 changes: 1 addition & 1 deletion forc-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ pub fn print_compiling(ty: Option<&TreeType>, name: &str, src: &dyn std::fmt::Di
Some(ty) => format!("{} ", program_type_str(ty)),
None => "".to_string(),
};
tracing::info!(
tracing::debug!(
" {} {ty}{} ({src})",
Colour::Green.bold().paint("Compiling"),
ansi_term::Style::new().bold().paint(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ impl AllocatedAbstractInstructionSet {
)
.0;

fn generate_mask(regs: &[&AllocatedRegister]) -> (VirtualImmediate24, VirtualImmediate24) {
let mask = regs.iter().fold((0, 0), |mut accum, reg| {
let reg_id = reg.to_reg_id().to_u8();
assert!((16..64).contains(&reg_id));
let reg_id = reg_id - 16;
let (mask_ref, bit) = if reg_id < 24 {
(&mut accum.0, reg_id)
} else {
(&mut accum.1, reg_id - 24)
};
// Set bit (from the least significant side) of mask_ref.
*mask_ref |= 1 << bit;
accum
});
(
VirtualImmediate24::new(mask.0, Span::dummy())
.expect("mask should have fit in 24b"),
VirtualImmediate24::new(mask.1, Span::dummy())
.expect("mask should have fit in 24b"),
)
}

// Now replace the PUSHA/POPA instructions with STOREs and LOADs.
self.ops = self.ops.drain(..).fold(Vec::new(), |mut new_ops, op| {
match &op.opcode {
Expand All @@ -94,35 +116,21 @@ impl AllocatedAbstractInstructionSet {
.chain([&AllocatedRegister::Constant(ConstantRegister::LocalsBase)])
.collect::<Vec<_>>();

let stack_use_bytes = regs.len() as u64 * 8;
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::MOVE(
AllocatedRegister::Constant(ConstantRegister::Scratch),
AllocatedRegister::Constant(ConstantRegister::StackPointer),
)),
comment: "save base stack value".into(),
owning_span: None,
});
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::CFEI(
VirtualImmediate24::new(stack_use_bytes, Span::dummy()).unwrap(),
)),
comment: "reserve space for saved registers".into(),
owning_span: None,
});

regs.into_iter().enumerate().for_each(|(idx, reg)| {
let store_op = AllocatedOpcode::SW(
AllocatedRegister::Constant(ConstantRegister::Scratch),
reg.clone(),
VirtualImmediate12::new(idx as u64, Span::dummy()).unwrap(),
);
let (mask_l, mask_h) = generate_mask(&regs);
if mask_l.value != 0 {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(store_op),
comment: format!("save {reg}"),
opcode: Either::Left(AllocatedOpcode::PSHL(mask_l)),
comment: "Save registers 16..40".into(),
owning_span: None,
});
})
}
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,
});
}
}

Either::Right(ControlFlowOp::PopAll(label)) => {
Expand All @@ -134,37 +142,21 @@ impl AllocatedAbstractInstructionSet {
.chain([&AllocatedRegister::Constant(ConstantRegister::LocalsBase)])
.collect::<Vec<_>>();

let stack_use_bytes = regs.len() as u64 * 8;
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::SUBI(
AllocatedRegister::Constant(ConstantRegister::Scratch),
AllocatedRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate12::new(stack_use_bytes, Span::dummy()).unwrap(),
)),
comment: "save base stack value".into(),
owning_span: None,
});

regs.into_iter().enumerate().for_each(|(idx, reg)| {
let load_op = AllocatedOpcode::LW(
reg.clone(),
AllocatedRegister::Constant(ConstantRegister::Scratch),
VirtualImmediate12::new(idx as u64, Span::dummy()).unwrap(),
);
let (mask_l, mask_h) = generate_mask(&regs);
if mask_h.value != 0 {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::POPH(mask_h)),
comment: "Restore registers 40..64".into(),
owning_span: None,
});
}
if mask_l.value != 0 {
new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(load_op),
comment: format!("restore {reg}"),
opcode: Either::Left(AllocatedOpcode::POPL(mask_l)),
comment: "Restore registers 16..40".into(),
owning_span: None,
});
});

new_ops.push(AllocatedAbstractOp {
opcode: Either::Left(AllocatedOpcode::CFSI(
VirtualImmediate24::new(stack_use_bytes, Span::dummy()).unwrap(),
)),
comment: "recover space from saved registers".into(),
owning_span: None,
});
}
}

_otherwise => new_ops.push(op),
Expand Down
17 changes: 16 additions & 1 deletion sway-core/src/asm_lang/allocated_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl fmt::Display for AllocatedRegister {
}

impl AllocatedRegister {
fn to_reg_id(&self) -> fuel_asm::RegId {
pub(crate) fn to_reg_id(&self) -> fuel_asm::RegId {
match self {
AllocatedRegister::Allocated(a) => fuel_asm::RegId::new(a + 16),
AllocatedRegister::Constant(constant) => constant.to_reg_id(),
Expand Down Expand Up @@ -152,6 +152,10 @@ pub(crate) enum AllocatedOpcode {
AllocatedRegister,
AllocatedRegister,
),
PSHH(VirtualImmediate24),
PSHL(VirtualImmediate24),
POPH(VirtualImmediate24),
POPL(VirtualImmediate24),
SB(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
SW(AllocatedRegister, AllocatedRegister, VirtualImmediate12),

Expand Down Expand Up @@ -309,6 +313,9 @@ impl AllocatedOpcode {
MCP(_r1, _r2, _r3) => vec![],
MCPI(_r1, _r2, _imm) => vec![],
MEQ(r1, _r2, _r3, _r4) => vec![r1],
PSHH(_mask) | PSHL(_mask) | POPH(_mask) | POPL(_mask) => {
panic!("Cannot determine defined registers for register PUSH/POP instructions")
}
SB(_r1, _r2, _i) => vec![],
SW(_r1, _r2, _i) => vec![],

Expand Down Expand Up @@ -431,6 +438,10 @@ impl fmt::Display for AllocatedOpcode {
MCP(a, b, c) => write!(fmtr, "mcp {a} {b} {c}"),
MCPI(a, b, c) => write!(fmtr, "mcpi {a} {b} {c}"),
MEQ(a, b, c, d) => write!(fmtr, "meq {a} {b} {c} {d}"),
PSHH(mask) => write!(fmtr, "pshh {mask}"),
PSHL(mask) => write!(fmtr, "pshl {mask}"),
POPH(mask) => write!(fmtr, "poph {mask}"),
POPL(mask) => write!(fmtr, "popl {mask}"),
SB(a, b, c) => write!(fmtr, "sb {a} {b} {c}"),
SW(a, b, c) => write!(fmtr, "sw {a} {b} {c}"),

Expand Down Expand Up @@ -596,6 +607,10 @@ impl AllocatedOp {
MEQ(a, b, c, d) => {
op::MEQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
PSHH(mask) => op::PSHH::new(mask.value.into()).into(),
PSHL(mask) => op::PSHL::new(mask.value.into()).into(),
POPH(mask) => op::POPH::new(mask.value.into()).into(),
POPL(mask) => op::POPL::new(mask.value.into()).into(),
SB(a, b, c) => op::SB::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
SW(a, b, c) => op::SW::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),

Expand Down
6 changes: 3 additions & 3 deletions sway-core/src/build_config.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::{path::PathBuf, sync::Arc};

use serde::{Deserialize, Serialize};
use strum::EnumString;
use std::{path::PathBuf, sync::Arc};
use strum::{Display, EnumString};

#[derive(
Clone,
Copy,
Debug,
Display,
Default,
Eq,
PartialEq,
Expand Down
Loading

0 comments on commit c67a5da

Please sign in to comment.