Skip to content
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

Add an is_reference_type::<T>() builtin. #1121

Merged
merged 1 commit into from
Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 69 additions & 24 deletions sway-core/src/asm_generation/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use super::*;
use crate::{
asm_lang::*,
parse_tree::{CallPath, Literal},
parse_tree::{BuiltinProperty, CallPath, Literal},
semantic_analysis::{
ast_node::{
SizeOfVariant, TypedAsmRegisterDeclaration, TypedCodeBlock, TypedEnumVariant,
TypedExpressionVariant,
TypedAsmRegisterDeclaration, TypedCodeBlock, TypedEnumVariant, TypedExpressionVariant,
},
TypedExpression,
},
Expand Down Expand Up @@ -340,8 +339,26 @@ pub(crate) fn convert_expression_to_asm(
namespace,
register_sequencer,
),
TypedExpressionVariant::SizeOf { variant } => convert_size_of_expression_to_asm(
variant,
TypedExpressionVariant::TypeProperty { property, type_id } => match property {
BuiltinProperty::SizeOfType => convert_size_of_to_asm(
None,
type_id,
namespace,
return_register,
register_sequencer,
exp.span.clone(),
),
BuiltinProperty::IsRefType => convert_is_ref_type_to_asm(
type_id,
namespace,
return_register,
register_sequencer,
exp.span.clone(),
),
},
TypedExpressionVariant::SizeOfValue { expr } => convert_size_of_to_asm(
Some(expr),
&expr.return_type,
namespace,
return_register,
register_sequencer,
Expand Down Expand Up @@ -422,34 +439,62 @@ fn convert_literal_to_asm(
}]
}

fn convert_size_of_expression_to_asm(
variant: &SizeOfVariant,
fn convert_is_ref_type_to_asm(
type_id: &TypeId,
namespace: &mut AsmNamespace,
return_register: &VirtualRegister,
register_sequencer: &mut RegisterSequencer,
span: Span,
) -> CompileResult<Vec<Op>> {
let mut warnings = vec![];
let warnings = vec![];
let mut errors = vec![];
let mut asm_buf = vec![];
let type_id = match variant {
SizeOfVariant::Val(exp) => {
asm_buf.push(Op::new_comment("size_of_val".to_string()));
let mut ops = check!(
convert_expression_to_asm(exp, namespace, return_register, register_sequencer),
vec![],
warnings,
errors
);
asm_buf.append(&mut ops);
exp.return_type
let mut asm_buf = vec![Op::new_comment("is_ref_type".to_string())];
let ty = match resolve_type(*type_id, &span) {
Ok(o) => o,
Err(e) => {
errors.push(e.into());
return err(warnings, errors);
}
SizeOfVariant::Type(ty) => {
asm_buf.push(Op::new_comment("size_of".to_string()));
*ty
};
let is_ref_type = match ty.is_copy_type(&span) {
Ok(is_copy) => !is_copy,
Err(e) => {
errors.push(e);
return err(warnings, errors);
}
};
let ty = match resolve_type(type_id, &span) {
let mut ops = convert_literal_to_asm(
&Literal::Boolean(is_ref_type),
namespace,
return_register,
register_sequencer,
span,
);
asm_buf.append(&mut ops);
ok(asm_buf, warnings, errors)
}

fn convert_size_of_to_asm(
expr: Option<&TypedExpression>,
type_id: &TypeId,
namespace: &mut AsmNamespace,
return_register: &VirtualRegister,
register_sequencer: &mut RegisterSequencer,
span: Span,
) -> CompileResult<Vec<Op>> {
let mut warnings = vec![];
let mut errors = vec![];
let mut asm_buf = vec![Op::new_comment("size_of_val".to_string())];
if let Some(expr) = expr {
let mut ops = check!(
convert_expression_to_asm(expr, namespace, return_register, register_sequencer),
vec![],
warnings,
errors
);
asm_buf.append(&mut ops);
}
let ty = match resolve_type(*type_id, &span) {
Ok(o) => o,
Err(e) => {
errors.push(e.into());
Expand Down
9 changes: 8 additions & 1 deletion sway-core/src/asm_generation/expression/subfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,14 @@ pub(crate) fn convert_subfield_to_asm(
}
};

asm_buf.push(if resolved_type_of_this_field.is_copy_type() {
let field_has_copy_type = match resolved_type_of_this_field.is_copy_type(&span) {
Ok(is_copy) => is_copy,
Err(e) => {
errors.push(e);
return err(warnings, errors);
}
};
asm_buf.push(if field_has_copy_type {
let offset_in_words = match VirtualImmediate12::new(offset_in_words, span.clone()) {
Ok(o) => o,
Err(e) => {
Expand Down
10 changes: 9 additions & 1 deletion sway-core/src/asm_generation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,7 +1430,15 @@ fn ret_or_retd_value(
);
}

if main_func_ret_ty.is_copy_type() {
let main_func_ret_ty_is_copy_type = match main_func_ret_ty.is_copy_type(&func.return_type_span)
{
Ok(is_copy) => is_copy,
Err(e) => {
errors.push(e);
return err(warnings, errors);
}
};
if main_func_ret_ty_is_copy_type {
asm_buf.push(Op {
owning_span: None,
opcode: Either::Left(VirtualOp::RET(return_register)),
Expand Down
32 changes: 15 additions & 17 deletions sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::{
parse_tree::{CallPath, Visibility},
semantic_analysis::{
ast_node::{
SizeOfVariant, TypedAbiDeclaration, TypedCodeBlock, TypedConstantDeclaration,
TypedDeclaration, TypedEnumDeclaration, TypedExpression, TypedExpressionVariant,
TypedAbiDeclaration, TypedCodeBlock, TypedConstantDeclaration, TypedDeclaration,
TypedEnumDeclaration, TypedExpression, TypedExpressionVariant,
TypedFunctionDeclaration, TypedReassignment, TypedReturnStatement,
TypedStructDeclaration, TypedStructExpressionField, TypedTraitDeclaration,
TypedVariableDeclaration, TypedWhileLoop,
Expand Down Expand Up @@ -1006,21 +1006,19 @@ fn connect_expression(
}
Ok(vec![this_ix])
}
SizeOf { variant } => match variant {
SizeOfVariant::Type(_) => Ok(vec![]),
SizeOfVariant::Val(exp) => {
let exp = connect_expression(
&(*exp).expression,
graph,
leaves,
exit_node,
"size_of",
tree_type,
exp.span.clone(),
)?;
Ok(exp)
}
},
TypeProperty { .. } => Ok(Vec::new()),
SizeOfValue { expr } => {
let expr = connect_expression(
&(*expr).expression,
graph,
leaves,
exit_node,
"size_of",
tree_type,
expr.span.clone(),
)?;
Ok(expr)
}
a => {
println!("Unimplemented: {:?}", a);
Err(CompileError::Unimplemented(
Expand Down
48 changes: 23 additions & 25 deletions sway-core/src/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;

use crate::{
asm_generation::from_ir::ir_type_size_in_bytes,
parse_tree::{AsmOp, AsmRegister, LazyOp, Literal, Visibility},
parse_tree::{AsmOp, AsmRegister, BuiltinProperty, LazyOp, Literal, Visibility},
semantic_analysis::{ast_node::*, *},
type_engine::*,
};
Expand Down Expand Up @@ -637,33 +637,31 @@ impl FnCompiler {
let span_md_idx = MetadataIndex::from_span(context, &access.span());
self.compile_storage_access(context, &access.fields, &access.ix, span_md_idx)
}
TypedExpressionVariant::SizeOf { variant } => {
match variant {
SizeOfVariant::Type(type_id) => {
let ir_type = convert_resolved_typeid_no_span(context, &type_id)?;
Ok(Constant::get_uint(
context,
64,
ir_type_size_in_bytes(context, &ir_type),
None,
))
}
SizeOfVariant::Val(exp) => {
let ir_type =
convert_resolved_typeid(context, &exp.return_type, &exp.span)?;

// Compile the expression in case of side-effects but ignore its value.
self.compile_expression(context, *exp)?;

Ok(Constant::get_uint(
context,
64,
ir_type_size_in_bytes(context, &ir_type),
None,
))
TypedExpressionVariant::TypeProperty { property, type_id } => {
let ir_type = convert_resolved_typeid_no_span(context, &type_id)?;
match property {
BuiltinProperty::SizeOfType => Ok(Constant::get_uint(
context,
64,
ir_type_size_in_bytes(context, &ir_type),
None,
)),
BuiltinProperty::IsRefType => {
Ok(Constant::get_bool(context, !ir_type.is_copy_type(), None))
}
}
}
TypedExpressionVariant::SizeOfValue { expr } => {
// Compile the expression in case of side-effects but ignore its value.
let ir_type = convert_resolved_typeid(context, &expr.return_type, &expr.span)?;
self.compile_expression(context, *expr)?;
Ok(Constant::get_uint(
context,
64,
ir_type_size_in_bytes(context, &ir_type),
None,
))
}
}
}

Expand Down
32 changes: 23 additions & 9 deletions sway-core/src/parse_tree/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,20 @@ pub enum Expression {
exp: Box<Expression>,
span: Span,
},
SizeOfType {
BuiltinGetTypeProperty {
builtin: BuiltinProperty,
type_name: TypeInfo,
type_span: Span,
span: Span,
},
}

#[derive(Debug, Clone, PartialEq)]
pub enum BuiltinProperty {
SizeOfType,
IsRefType,
}

#[derive(Debug, Clone)]
pub enum DelayedResolutionVariant {
StructField(DelayedStructFieldResolution),
Expand Down Expand Up @@ -312,7 +319,7 @@ impl Expression {
StorageAccess { span, .. } => span,
IfLet { span, .. } => span,
SizeOfVal { span, .. } => span,
SizeOfType { span, .. } => span,
BuiltinGetTypeProperty { span, .. } => span,
})
.clone()
}
Expand Down Expand Up @@ -1266,8 +1273,8 @@ impl Expression {
warnings,
errors
),
Rule::size_of_expr => check!(
parse_size_of_expr(expr, config),
Rule::built_in_expr => check!(
parse_built_in_expr(expr, config),
return err(warnings, errors),
warnings,
errors
Expand Down Expand Up @@ -1439,7 +1446,7 @@ pub(crate) fn parse_array_index(
)
}

pub(crate) fn parse_size_of_expr(
pub(crate) fn parse_built_in_expr(
item: Pair<Rule>,
config: Option<&BuildConfig>,
) -> CompileResult<ParserLifter<Expression>> {
Expand Down Expand Up @@ -1471,10 +1478,12 @@ pub(crate) fn parse_size_of_expr(
value: exp,
}
}
Rule::size_of_type_expr => {
// The size_of_type and is_ref_type_expr rules have identical grammar apart from the
// keyword.
Rule::size_of_type_expr | Rule::is_ref_type_expr => {
let mut inner_iter = size_of.into_inner();
let _keyword = inner_iter.next();
let elem = inner_iter.next().expect("guarenteed by grammar");
let keyword = inner_iter.next().expect("guaranteed by grammar");
let elem = inner_iter.next().expect("guaranteed by grammar");
let type_span = Span {
span: elem.as_span(),
path: config.map(|c| c.path()),
Expand All @@ -1485,7 +1494,12 @@ pub(crate) fn parse_size_of_expr(
warnings,
errors
);
let exp = Expression::SizeOfType {
let exp = Expression::BuiltinGetTypeProperty {
builtin: match keyword.as_str() {
"size_of" => BuiltinProperty::SizeOfType,
"is_reference_type" => BuiltinProperty::IsRefType,
_otherwise => unreachable!("unexpected built in keyword: {keyword}"),
},
type_name,
type_span,
span,
Expand Down
Loading