Skip to content

Commit

Permalink
Correctly export the main fn in the json abi (#5707)
Browse files Browse the repository at this point in the history
## Description

This fixes a bug introduced by
#5427, where the ABI was exporting
the "__entry" function instead of the "main".

When parsing and type checking I now mark function as "main" an only
later decide if the compilation will call the main or the entry.

I also moved the `is_entrypoint` method from the `TyAstNode` to the DCE
pass, because it is super specific to that pass.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] 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).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
xunilrj authored Mar 7, 2024
1 parent c1c2501 commit a0b8062
Show file tree
Hide file tree
Showing 18 changed files with 305 additions and 196 deletions.
10 changes: 2 additions & 8 deletions sway-core/src/abi_generation/fuel_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,8 @@ pub fn generate_program_abi(
configurables: Some(configurables),
}
}
TyProgramKind::Script {
entry_function: main_function,
..
}
| TyProgramKind::Predicate {
entry_function: main_function,
..
} => {
TyProgramKind::Script { main_function, .. }
| TyProgramKind::Predicate { main_function, .. } => {
let main_function = decl_engine.get_function(main_function);
let functions =
vec![main_function.generate_abi_function(ctx, type_engine, decl_engine, types)];
Expand Down
93 changes: 90 additions & 3 deletions sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
decl_engine::*,
language::{
parsed::TreeType,
ty::{self, TyAstNodeContent, TyImplItem},
ty::{
self, ConstantDecl, FunctionDecl, StructDecl, TraitDecl, TyAstNode, TyAstNodeContent,
TyDecl, TyImplItem, TypeAliasDecl,
},
CallPath, Visibility,
},
transform::{self, AttributesMap},
Expand All @@ -24,6 +27,88 @@ use sway_types::{
Ident, Named, Spanned,
};

// Defines if this node starts the dca graph or not
fn is_entry_point(node: &TyAstNode, decl_engine: &DeclEngine, tree_type: &TreeType) -> bool {
match tree_type {
TreeType::Predicate | TreeType::Script => {
// Predicates and scripts have main and test functions as entry points.
match node {
TyAstNode {
span: _,
content:
TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
decl_id,
..
})),
..
} => {
let decl = decl_engine.get_function(decl_id);
decl.is_entry() || decl.is_main() || decl.is_test()
}
_ => false,
}
}
TreeType::Contract | TreeType::Library { .. } => match node {
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
decl_id,
decl_span: _,
..
})),
..
} => {
let decl = decl_engine.get_function(decl_id);
decl.visibility == Visibility::Public || decl.is_test()
}
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::TraitDecl(TraitDecl {
decl_id,
decl_span: _,
..
})),
..
} => decl_engine.get_trait(decl_id).visibility.is_public(),
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::StructDecl(StructDecl { decl_id, .. })),
..
} => {
let struct_decl = decl_engine.get_struct(decl_id);
struct_decl.visibility == Visibility::Public
}
TyAstNode {
content: TyAstNodeContent::Declaration(TyDecl::ImplTrait { .. }),
..
} => true,
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::ConstantDecl(ConstantDecl {
decl_id,
decl_span: _,
..
})),
..
} => {
let decl = decl_engine.get_constant(decl_id);
decl.visibility.is_public()
}
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::TypeAliasDecl(TypeAliasDecl {
decl_id, ..
})),
..
} => {
let decl = decl_engine.get_type_alias(decl_id);
decl.visibility.is_public()
}
_ => false,
},
}
}

impl<'cfg> ControlFlowGraph<'cfg> {
pub(crate) fn find_dead_code(&self, decl_engine: &DeclEngine) -> Vec<CompileWarning> {
// Dead code is code that has no path from the entry point.
Expand Down Expand Up @@ -287,13 +372,15 @@ impl<'cfg> ControlFlowGraph<'cfg> {

let mut entry_points = vec![];
let mut non_entry_points = vec![];

for ast_node in module_nodes {
if ast_node.is_entry_point(decl_engine, tree_type) {
if is_entry_point(ast_node, decl_engine, tree_type) {
entry_points.push(ast_node);
} else {
non_entry_points.push(ast_node);
}
}

for ast_entrypoint in non_entry_points.into_iter().chain(entry_points) {
let (_l_leaves, _new_exit_node) = connect_node(
engines,
Expand All @@ -320,7 +407,7 @@ fn collect_entry_points(
for i in graph.node_indices() {
let is_entry = match &graph[i] {
ControlFlowGraphNode::ProgramNode { node, .. } => {
node.is_entry_point(decl_engine, tree_type)
is_entry_point(node, decl_engine, tree_type)
}
_ => false,
};
Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/ir_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn compile_program<'eng>(
match kind {
// predicates and scripts have the same codegen, their only difference is static
// type-check time checks.
ty::TyProgramKind::Script { entry_function } => compile::compile_script(
ty::TyProgramKind::Script { entry_function, .. } => compile::compile_script(
engines,
&mut ctx,
entry_function,
Expand All @@ -73,7 +73,7 @@ pub fn compile_program<'eng>(
&messages_types,
&test_fns,
),
ty::TyProgramKind::Predicate { entry_function } => compile::compile_predicate(
ty::TyProgramKind::Predicate { entry_function, .. } => compile::compile_predicate(
engines,
&mut ctx,
entry_function,
Expand Down
12 changes: 6 additions & 6 deletions sway-core/src/ir_generation/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::{collections::HashMap, sync::Arc};
pub(super) fn compile_script(
engines: &Engines,
context: &mut Context,
main_function: &DeclId<ty::TyFunctionDecl>,
entry_function: &DeclId<ty::TyFunctionDecl>,
namespace: &namespace::Module,
declarations: &[ty::TyDecl],
logged_types_map: &HashMap<TypeId, LogId>,
Expand All @@ -49,7 +49,7 @@ pub(super) fn compile_script(
context,
&mut md_mgr,
module,
main_function,
entry_function,
logged_types_map,
messages_types_map,
None,
Expand All @@ -71,7 +71,7 @@ pub(super) fn compile_script(
pub(super) fn compile_predicate(
engines: &Engines,
context: &mut Context,
main_function: &DeclId<ty::TyFunctionDecl>,
entry_function: &DeclId<ty::TyFunctionDecl>,
namespace: &namespace::Module,
declarations: &[ty::TyDecl],
logged_types: &HashMap<TypeId, LogId>,
Expand All @@ -96,7 +96,7 @@ pub(super) fn compile_predicate(
context,
&mut md_mgr,
module,
main_function,
entry_function,
&HashMap::new(),
&HashMap::new(),
None,
Expand All @@ -117,7 +117,7 @@ pub(super) fn compile_predicate(
#[allow(clippy::too_many_arguments)]
pub(super) fn compile_contract(
context: &mut Context,
main_function: Option<&DeclId<ty::TyFunctionDecl>>,
entry_function: Option<&DeclId<ty::TyFunctionDecl>>,
abi_entries: &[DeclId<ty::TyFunctionDecl>],
namespace: &namespace::Module,
declarations: &[ty::TyDecl],
Expand All @@ -140,7 +140,7 @@ pub(super) fn compile_contract(
)
.map_err(|err| vec![err])?;

if let Some(main_function) = main_function {
if let Some(main_function) = entry_function {
compile_entry_function(
engines,
context,
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/language/parsed/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use sway_types::{ident::Ident, span::Span};
pub enum FunctionDeclarationKind {
Default,
Entry,
Main,
Test,
}

Expand Down
86 changes: 1 addition & 85 deletions sway-core/src/language/ty/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use sway_types::{Ident, Span};
use crate::{
decl_engine::*,
engine_threading::*,
language::{parsed::TreeType, ty::*, Visibility},
language::ty::*,
semantic_analysis::{
TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization,
TypeCheckFinalizationContext,
Expand Down Expand Up @@ -192,90 +192,6 @@ impl TyAstNode {
}
}

pub(crate) fn is_entry_point(&self, decl_engine: &DeclEngine, tree_type: &TreeType) -> bool {
match tree_type {
TreeType::Predicate | TreeType::Script => {
// Predicates and scripts have main and test functions as entry points.
match self {
TyAstNode {
span: _,
content:
TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
decl_id,
..
})),
..
} => {
let decl = decl_engine.get_function(decl_id);
decl.is_entry_or_test()
}
_ => false,
}
}
TreeType::Contract | TreeType::Library { .. } => match self {
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::FunctionDecl(FunctionDecl {
decl_id,
decl_span: _,
..
})),
..
} => {
let decl = decl_engine.get_function(decl_id);
decl.visibility == Visibility::Public || decl.is_test()
}
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::TraitDecl(TraitDecl {
decl_id,
decl_span: _,
..
})),
..
} => decl_engine.get_trait(decl_id).visibility.is_public(),
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::StructDecl(StructDecl {
decl_id, ..
})),
..
} => {
let struct_decl = decl_engine.get_struct(decl_id);
struct_decl.visibility == Visibility::Public
}
TyAstNode {
content: TyAstNodeContent::Declaration(TyDecl::ImplTrait { .. }),
..
} => true,
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::ConstantDecl(ConstantDecl {
decl_id,
decl_span: _,
..
})),
..
} => {
let decl = decl_engine.get_constant(decl_id);
decl.visibility.is_public()
}
TyAstNode {
content:
TyAstNodeContent::Declaration(TyDecl::TypeAliasDecl(TypeAliasDecl {
decl_id,
..
})),
..
} => {
let decl = decl_engine.get_type_alias(decl_id);
decl.visibility.is_public()
}
_ => false,
},
}
}

pub(crate) fn type_info(&self, type_engine: &TypeEngine) -> TypeInfo {
// return statement should be ()
match &self.content {
Expand Down
11 changes: 6 additions & 5 deletions sway-core/src/language/ty/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use sway_types::{
pub enum TyFunctionDeclKind {
Default,
Entry,
Main,
Test,
}

Expand Down Expand Up @@ -336,6 +337,7 @@ impl TyFunctionDecl {
FunctionDeclarationKind::Default => TyFunctionDeclKind::Default,
FunctionDeclarationKind::Entry => TyFunctionDeclKind::Entry,
FunctionDeclarationKind::Test => TyFunctionDeclKind::Test,
FunctionDeclarationKind::Main => TyFunctionDeclKind::Main,
},
}
}
Expand Down Expand Up @@ -412,6 +414,10 @@ impl TyFunctionDecl {
matches!(self.kind, TyFunctionDeclKind::Entry)
}

pub fn is_main(&self) -> bool {
matches!(self.kind, TyFunctionDeclKind::Main)
}

/// Whether or not this function is a unit test, i.e. decorated with `#[test]`.
pub fn is_test(&self) -> bool {
//TODO match kind to Test
Expand All @@ -435,11 +441,6 @@ impl TyFunctionDecl {
}
}

/// Whether or not this function describes a program entry point.
pub fn is_entry_or_test(&self) -> bool {
self.is_entry() || self.is_test()
}

/// Whether or not this function is a constructor for the type given by `type_id`.
///
/// Returns `Some(true)` if the function is surely the constructor and `Some(false)` if
Expand Down
Loading

0 comments on commit a0b8062

Please sign in to comment.