Skip to content

Commit

Permalink
[move][ir-to-bytecode] Add source locations to Type in the Move IR (#…
Browse files Browse the repository at this point in the history
…19875)

## Description 

Plumbs in source locations for `Type`s in the Move IR. This will be
useful for adding return types to the Move source maps.

## Test plan 

Make sure existing types pass. 

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
tzakian authored Oct 16, 2024
1 parent 31b15dd commit 692f6c6
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 122 deletions.
30 changes: 15 additions & 15 deletions external-crates/move/crates/module-generation/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,12 @@ impl<'a> ModuleGenerator<'a> {
if !structs.is_empty() {
end += 1;
};

match self.index(end) {
0 => Type::Address,
1 => Type::U8,
2 => Type::U64,
3 => Type::U128,
4 => Type::Bool,
let type_ = match self.index(end) {
0 => Type_::Address,
1 => Type_::U8,
2 => Type_::U64,
3 => Type_::U128,
4 => Type_::Bool,
5 if !structs.is_empty() => {
let index = self.index(structs.len());
let struct_def = structs[index].value.clone();
Expand All @@ -133,17 +132,18 @@ impl<'a> ModuleGenerator<'a> {
let module_name = ModuleName::module_self();
QualifiedDatatypeIdent::new(module_name, struct_name)
};
Type::Datatype(struct_ident, ty_instants)
Type_::Datatype(struct_ident, ty_instants)
}
6 => Type::U16,
7 => Type::U32,
8 => Type::U256,
6 => Type_::U16,
7 => Type_::U32,
8 => Type_::U256,
_ => {
let index = self.index(ty_param_context.len());
let ty_var = ty_param_context[index].value.clone();
Type::TypeParameter(ty_var)
Type_::TypeParameter(ty_var)
}
}
};
Spanned::unsafe_no_loc(type_)
}

fn typ(&mut self, ty_param_context: &[(TypeVar, BTreeSet<Ability>)]) -> Type {
Expand All @@ -158,7 +158,7 @@ impl<'a> ModuleGenerator<'a> {
// if typ.is_nominal_resource { .... }
if self.options.references_allowed && self.gen.gen_bool(0.25) {
let is_mutable = self.gen.gen_bool(0.25);
Type::Reference(is_mutable, Box::new(typ))
Spanned::unsafe_no_loc(Type_::Reference(is_mutable, Box::new(typ)))
} else {
typ
}
Expand Down Expand Up @@ -209,7 +209,7 @@ impl<'a> ModuleGenerator<'a> {
.iter()
.map(|(ty_var_, _)| {
let param_name = Spanned::unsafe_no_loc(Var_(self.identifier().into()));
let ty = Type::TypeParameter(ty_var_.value.clone());
let ty = Spanned::unsafe_no_loc(Type_::TypeParameter(ty_var_.value.clone()));
(param_name, ty)
})
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -811,11 +811,11 @@ fn base_types(context: &mut Context, bs: Vec<H::BaseType>) -> Vec<IR::Type> {
bs.into_iter().map(|b| base_type(context, b)).collect()
}

fn base_type(context: &mut Context, sp!(_, bt_): H::BaseType) -> IR::Type {
fn base_type(context: &mut Context, sp!(bt_loc, bt_): H::BaseType) -> IR::Type {
use BuiltinTypeName_ as BT;
use H::{BaseType_ as B, TypeName_ as TN};
use IR::Type as IRT;
match bt_ {
use IR::Type_ as IRT;
let type_ = match bt_ {
B::Unreachable | B::UnresolvedError => {
panic!("ICE should not have reached compilation if there are errors")
}
Expand Down Expand Up @@ -845,15 +845,19 @@ fn base_type(context: &mut Context, sp!(_, bt_): H::BaseType) -> IR::Type {
user_specified_name,
..
}) => IRT::TypeParameter(type_var(user_specified_name).value),
}
};
sp(bt_loc, type_)
}

fn single_type(context: &mut Context, sp!(_, st_): H::SingleType) -> IR::Type {
fn single_type(context: &mut Context, sp!(st_loc, st_): H::SingleType) -> IR::Type {
use H::SingleType_ as S;
use IR::Type as IRT;
use IR::Type_ as IRT;
match st_ {
S::Base(bt) => base_type(context, bt),
S::Ref(mut_, bt) => IRT::Reference(mut_, Box::new(base_type(context, bt))),
S::Ref(mut_, bt) => sp(
st_loc,
IRT::Reference(mut_, Box::new(base_type(context, bt))),
),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1330,72 +1330,74 @@ fn parse_ability(tokens: &mut Lexer) -> Result<(Ability, Loc), ParseError<Loc, a
// }

fn parse_type(tokens: &mut Lexer) -> Result<Type, ParseError<Loc, anyhow::Error>> {
let start_loc = tokens.start_loc();
let t = match tokens.peek() {
Tok::NameValue if matches!(tokens.content(), "address") => {
tokens.advance()?;
Type::Address
Type_::Address
}
Tok::NameValue if matches!(tokens.content(), "u8") => {
tokens.advance()?;
Type::U8
Type_::U8
}
Tok::NameValue if matches!(tokens.content(), "u16") => {
tokens.advance()?;
Type::U16
Type_::U16
}
Tok::NameValue if matches!(tokens.content(), "u32") => {
tokens.advance()?;
Type::U32
Type_::U32
}
Tok::NameValue if matches!(tokens.content(), "u64") => {
tokens.advance()?;
Type::U64
Type_::U64
}
Tok::NameValue if matches!(tokens.content(), "u128") => {
tokens.advance()?;
Type::U128
Type_::U128
}
Tok::NameValue if matches!(tokens.content(), "u256") => {
tokens.advance()?;
Type::U256
Type_::U256
}
Tok::NameValue if matches!(tokens.content(), "bool") => {
tokens.advance()?;
Type::Bool
Type_::Bool
}
Tok::NameValue if matches!(tokens.content(), "signer") => {
tokens.advance()?;
Type::Signer
Type_::Signer
}
Tok::NameBeginTyValue if matches!(tokens.content(), "vector<") => {
tokens.advance()?;
let ty = parse_type(tokens)?;
adjust_token(tokens, &[Tok::Greater])?;
consume_token(tokens, Tok::Greater)?;
Type::Vector(Box::new(ty))
Type_::Vector(Box::new(ty))
}
Tok::DotNameValue => {
let s = parse_qualified_struct_ident(tokens)?;
let tys = parse_type_actuals(tokens)?;
Type::Datatype(s, tys)
Type_::Datatype(s, tys)
}
Tok::Amp => {
tokens.advance()?;
Type::Reference(false, Box::new(parse_type(tokens)?))
Type_::Reference(false, Box::new(parse_type(tokens)?))
}
Tok::AmpMut => {
tokens.advance()?;
Type::Reference(true, Box::new(parse_type(tokens)?))
Type_::Reference(true, Box::new(parse_type(tokens)?))
}
Tok::NameValue => Type::TypeParameter(TypeVar_(parse_name(tokens)?)),
Tok::NameValue => Type_::TypeParameter(TypeVar_(parse_name(tokens)?)),
t => {
return Err(ParseError::InvalidToken {
location: current_token_loc(tokens),
message: format!("invalid token kind for type {:?}", t),
})
}
};
Ok(t)
let end_loc = tokens.previous_end_loc();
Ok(spanned(tokens.file_hash(), start_loc, end_loc, t))
}

// TypeVar: TypeVar = {
Expand Down
98 changes: 55 additions & 43 deletions external-crates/move/crates/move-ir-to-bytecode/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ fn constant_name_as_constant_value_index(
) -> Result<ConstantPoolIndex> {
let name_constant = compile_constant(
context,
Type::Vector(Box::new(Type::U8)),
&MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)),
MoveValue::vector_u8(const_name.to_string().into_bytes()),
)?;
context.constant_index(name_constant)
Expand Down Expand Up @@ -407,7 +407,11 @@ pub fn compile_module<'a>(
constant_name_as_constant_value_index(&mut context, &ir_constant.name)?;
}

let constant = compile_constant(&mut context, ir_constant.signature, ir_constant.value)?;
let constant = compile_constant(
&mut context,
&type_to_constant_type_layout(ir_constant.signature)?,
ir_constant.value,
)?;
context.declare_constant(ir_constant.name.clone(), constant.clone())?;
let const_idx = context.constant_index(constant)?;
record_src_loc!(const_decl: context, const_idx, ir_constant.name);
Expand Down Expand Up @@ -672,30 +676,30 @@ fn compile_type(
type_parameters: &HashMap<TypeVar_, TypeParameterIndex>,
ty: &Type,
) -> Result<SignatureToken> {
Ok(match ty {
Type::Address => SignatureToken::Address,
Type::Signer => SignatureToken::Signer,
Type::U8 => SignatureToken::U8,
Type::U16 => SignatureToken::U16,
Type::U32 => SignatureToken::U32,
Type::U64 => SignatureToken::U64,
Type::U128 => SignatureToken::U128,
Type::U256 => SignatureToken::U256,
Type::Bool => SignatureToken::Bool,
Type::Vector(inner_type) => SignatureToken::Vector(Box::new(compile_type(
Ok(match &ty.value {
Type_::Address => SignatureToken::Address,
Type_::Signer => SignatureToken::Signer,
Type_::U8 => SignatureToken::U8,
Type_::U16 => SignatureToken::U16,
Type_::U32 => SignatureToken::U32,
Type_::U64 => SignatureToken::U64,
Type_::U128 => SignatureToken::U128,
Type_::U256 => SignatureToken::U256,
Type_::Bool => SignatureToken::Bool,
Type_::Vector(inner_type) => SignatureToken::Vector(Box::new(compile_type(
context,
type_parameters,
inner_type,
)?)),
Type::Reference(is_mutable, inner_type) => {
Type_::Reference(is_mutable, inner_type) => {
let inner_token = Box::new(compile_type(context, type_parameters, inner_type)?);
if *is_mutable {
SignatureToken::MutableReference(inner_token)
} else {
SignatureToken::Reference(inner_token)
}
}
Type::Datatype(ident, tys) => {
Type_::Datatype(ident, tys) => {
let sh_idx = context.datatype_handle_index(ident.clone())?;

if tys.is_empty() {
Expand All @@ -705,7 +709,7 @@ fn compile_type(
SignatureToken::DatatypeInstantiation(Box::new((sh_idx, tokens)))
}
}
Type::TypeParameter(ty_var) => {
Type_::TypeParameter(ty_var) => {
let idx = match type_parameters.get(ty_var) {
None => bail!("Unbound type parameter {}", ty_var),
Some(idx) => *idx,
Expand Down Expand Up @@ -1267,7 +1271,7 @@ fn compile_expression(
Exp_::Value(cv) => match cv.value {
CopyableVal_::Address(address) => {
let address_value = MoveValue::Address(address);
let constant = compile_constant(context, Type::Address, address_value)?;
let constant = compile_constant(context, &MoveTypeLayout::Address, address_value)?;
let idx = context.constant_index(constant)?;
push_instr!(exp.loc, Bytecode::LdConst(idx));
function_frame.push()?;
Expand Down Expand Up @@ -1298,8 +1302,8 @@ fn compile_expression(
}
CopyableVal_::ByteArray(buf) => {
let vec_value = MoveValue::vector_u8(buf);
let ty = Type::Vector(Box::new(Type::U8));
let constant = compile_constant(context, ty, vec_value)?;
let ty = MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8));
let constant = compile_constant(context, &ty, vec_value)?;
let idx = context.constant_index(constant)?;
push_instr!(exp.loc, Bytecode::LdConst(idx));
function_frame.push()?;
Expand Down Expand Up @@ -1669,30 +1673,38 @@ fn compile_call(
Ok(())
}

fn compile_constant(_context: &mut Context, ty: Type, value: MoveValue) -> Result<Constant> {
fn type_layout(ty: Type) -> Result<MoveTypeLayout> {
Ok(match ty {
Type::Address => MoveTypeLayout::Address,
Type::Signer => MoveTypeLayout::Signer,
Type::U8 => MoveTypeLayout::U8,
Type::U16 => MoveTypeLayout::U16,
Type::U32 => MoveTypeLayout::U32,
Type::U64 => MoveTypeLayout::U64,
Type::U128 => MoveTypeLayout::U128,
Type::U256 => MoveTypeLayout::U256,
Type::Bool => MoveTypeLayout::Bool,
Type::Vector(inner_type) => MoveTypeLayout::Vector(Box::new(type_layout(*inner_type)?)),
Type::Reference(_, _) => bail!("References are not supported in constant type layouts"),
Type::TypeParameter(_) => {
bail!("Type parameters are not supported in constant type layouts")
}
Type::Datatype(_ident, _tys) => {
bail!("TODO Structs are not *yet* supported in constant type layouts")
}
})
}
fn type_to_constant_type_layout(ty: Type) -> Result<MoveTypeLayout> {
Ok(match ty.value {
Type_::Address => MoveTypeLayout::Address,
Type_::Signer => MoveTypeLayout::Signer,
Type_::U8 => MoveTypeLayout::U8,
Type_::U16 => MoveTypeLayout::U16,
Type_::U32 => MoveTypeLayout::U32,
Type_::U64 => MoveTypeLayout::U64,
Type_::U128 => MoveTypeLayout::U128,
Type_::U256 => MoveTypeLayout::U256,
Type_::Bool => MoveTypeLayout::Bool,
Type_::Vector(inner_type) => {
MoveTypeLayout::Vector(Box::new(type_to_constant_type_layout(*inner_type)?))
}
Type_::Reference(_, _) => {
bail!("References are not supported in constant type layouts")
}
Type_::TypeParameter(_) => {
bail!("Type parameters are not supported in constant type layouts")
}
Type_::Datatype(_ident, _tys) => {
bail!("TODO Structs are not *yet* supported in constant type layouts")
}
})
}

Constant::serialize_constant(&type_layout(ty)?, &value)
fn compile_constant(
_context: &mut Context,
layout: &MoveTypeLayout,
value: MoveValue,
) -> Result<Constant> {
Constant::serialize_constant(layout, &value)
.ok_or_else(|| format_err!("Could not serialize constant"))
}

Expand Down Expand Up @@ -1793,7 +1805,7 @@ fn compile_bytecode(
IRBytecode_::LdTrue => Bytecode::LdTrue,
IRBytecode_::LdFalse => Bytecode::LdFalse,
IRBytecode_::LdConst(ty, v) => {
let constant = compile_constant(context, ty, v)?;
let constant = compile_constant(context, &type_to_constant_type_layout(ty)?, v)?;
Bytecode::LdConst(context.constant_index(constant)?)
}
IRBytecode_::LdNamedConst(c) => Bytecode::LdConst(context.named_constant_index(&c)?),
Expand Down
Loading

0 comments on commit 692f6c6

Please sign in to comment.