-
Notifications
You must be signed in to change notification settings - Fork 289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor move runtime #4166
Refactor move runtime #4166
Changes from all commits
9125f45
08e1a2b
b2590d4
c368630
476efe6
7c3822e
ce69c4e
75b9388
762e0fe
53a21df
e2973a9
f151c83
c306dbc
da480be
1b9352c
31287e9
45ffb99
98e14c8
d9530c1
28c2745
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// Copyright (c) The Starcoin Core Contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use move_core_types::{ | ||
account_address::AccountAddress, identifier::Identifier, language_storage::ModuleId, | ||
}; | ||
use move_model::{ | ||
ast::Attribute, | ||
model::{FunctionEnv, GlobalEnv, Loc, ModuleEnv, QualifiedId, StructId}, | ||
symbol::Symbol, | ||
ty::{PrimitiveType, Type}, | ||
}; | ||
use std::rc::Rc; | ||
|
||
pub(crate) fn run_extended_checks(env: &GlobalEnv) { | ||
let checker = ExtendedChecker::new(env); | ||
checker.run(); | ||
} | ||
|
||
struct ExtendedChecker<'a> { | ||
env: &'a GlobalEnv, | ||
/// The id of the module defining error categories | ||
#[allow(unused)] | ||
error_category_module: ModuleId, | ||
} | ||
|
||
impl<'a> ExtendedChecker<'a> { | ||
fn new(env: &'a GlobalEnv) -> Self { | ||
Self { | ||
env, | ||
error_category_module: ModuleId::new( | ||
AccountAddress::ONE, | ||
Identifier::new("error").unwrap(), | ||
), | ||
} | ||
} | ||
|
||
// see implementation in `aptos-core` | ||
// https://github.com/aptos-labs/aptos-core/blob/3af88bc872221c4958e6163660c60bc07bf53d38/aptos-move/framework/src/extended_checks.rs#L123 | ||
fn run(&self) { | ||
for ref module in self.env.get_modules() { | ||
if module.is_target() { | ||
self.check_entry_functions(module); | ||
self.check_init_module(module); | ||
self.build_error_map(module); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// ------------------------------------------------------------------------------------------------- | ||
// Helper functions | ||
|
||
impl<'a> ExtendedChecker<'a> { | ||
fn has_attribute(&self, fun: &FunctionEnv, attr_name: &str) -> bool { | ||
self.has_attribute_iter(fun.get_attributes().iter(), attr_name) | ||
} | ||
|
||
fn has_attribute_iter( | ||
&self, | ||
mut attrs: impl Iterator<Item = &'a Attribute>, | ||
attr_name: &str, | ||
) -> bool { | ||
attrs.any(|attr| { | ||
if let Attribute::Apply(_, name, _) = attr { | ||
self.env.symbol_pool().string(*name).as_str() == attr_name | ||
} else { | ||
false | ||
} | ||
}) | ||
} | ||
|
||
#[allow(unused)] | ||
fn get_runtime_module_id(&self, module: &ModuleEnv<'_>) -> ModuleId { | ||
let name = module.get_name(); | ||
let addr = AccountAddress::from_hex_literal(&format!("0x{:x}", name.addr())).unwrap(); | ||
let name = Identifier::new(self.name_string(name.name()).to_string()).unwrap(); | ||
ModuleId::new(addr, name) | ||
} | ||
|
||
#[allow(unused)] | ||
fn name_string(&self, symbol: Symbol) -> Rc<String> { | ||
self.env.symbol_pool().string(symbol) | ||
} | ||
} | ||
|
||
// ------------------------------------------------------------------------------------------------- | ||
// Module Initialization | ||
|
||
impl<'a> ExtendedChecker<'a> { | ||
fn check_init_module(&self, _module: &ModuleEnv) { | ||
// TODO(simon): implement me. | ||
} | ||
} | ||
|
||
// ------------------------------------------------------------------------------------------------- | ||
// Entry Functions | ||
|
||
impl<'a> ExtendedChecker<'a> { | ||
fn check_entry_functions(&self, module: &ModuleEnv) { | ||
for ref fun in module.get_functions() { | ||
if !fun.is_entry() { | ||
continue; | ||
} | ||
|
||
if self.has_attribute(fun, "legacy_entry_function") { | ||
continue; | ||
} | ||
|
||
self.check_transaction_args(&fun.get_id_loc(), &fun.get_parameter_types()); | ||
if fun.get_return_count() > 0 { | ||
self.env | ||
.error(&fun.get_id_loc(), "entry function cannot return values") | ||
} | ||
} | ||
} | ||
|
||
fn check_transaction_args(&self, loc: &Loc, args: &[Type]) { | ||
for ty in args { | ||
self.check_transaction_input_type(loc, ty); | ||
} | ||
} | ||
|
||
fn check_transaction_input_type(&self, loc: &Loc, ty: &Type) { | ||
use Type::*; | ||
match ty { | ||
Primitive(_) | TypeParameter(_) => { | ||
// Any primitive type allowed, any parameter expected to instantiate with primitive | ||
} | ||
//todo(simon): give it a try to change me to Reference(ReferenceKind::Immutable, bt) | ||
Reference(false, bt) if matches!(bt.as_ref(), Primitive(PrimitiveType::Signer)) => { | ||
// Reference to signer allowed | ||
} | ||
Vector(ety) => { | ||
// Vectors are allowed if element type is allowed | ||
self.check_transaction_input_type(loc, ety) | ||
} | ||
Struct(mid, sid, _) if self.is_allowed_input_struct(mid.qualified(*sid)) => { | ||
// Specific struct types are allowed | ||
} | ||
_ => { | ||
// Everything else is disallowed. | ||
self.env.error( | ||
loc, | ||
&format!( | ||
"type `{}` is not supported as a parameter type", | ||
ty.display(&self.env.get_type_display_ctx()) | ||
), | ||
); | ||
} | ||
} | ||
} | ||
|
||
fn is_allowed_input_struct(&self, qid: QualifiedId<StructId>) -> bool { | ||
let name = self.env.get_struct(qid).get_full_name_with_address(); | ||
// TODO(simon) find a nice way to keep this in sync with allowed_structs in starcoin-vm | ||
matches!( | ||
name.as_str(), | ||
"0x1::string::String" | ||
| "0x1::object::Object" | ||
| "0x1::option::Option" | ||
| "0x1::fixed_point32::FixedPoint32" | ||
| "0x1::fixed_point64::FixedPoint64" | ||
) | ||
} | ||
} | ||
|
||
// ------------------------------------------------------------------------------------------------- | ||
// Build errors map | ||
|
||
impl<'a> ExtendedChecker<'a> { | ||
fn build_error_map(&self, _module: &ModuleEnv) { | ||
// TODO(simon): implement me. | ||
} | ||
Comment on lines
+171
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement The Do you need help implementing this method or would you like me to open a GitHub issue to track this task? |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement
check_init_module
method.The
check_init_module
method is currently not implemented. Consider implementing this method or providing more details on what needs to be done.Do you need help implementing this method or would you like me to open a GitHub issue to track this task?