From 535e6482142a0dbc71ed1fe72b86ee212786c798 Mon Sep 17 00:00:00 2001 From: salaheldinsoliman Date: Wed, 24 Jul 2024 22:11:13 +0200 Subject: [PATCH] feat: optimize string printing Signed-off-by: salaheldinsoliman --- src/codegen/dispatch/soroban.rs | 6 --- src/emit/expression.rs | 34 +++++++++++- src/emit/instructions.rs | 2 + src/emit/soroban/mod.rs | 9 ---- src/emit/soroban/target.rs | 93 ++++++++++++++++++++++++--------- src/emit/strings.rs | 4 ++ 6 files changed, 107 insertions(+), 41 deletions(-) diff --git a/src/codegen/dispatch/soroban.rs b/src/codegen/dispatch/soroban.rs index 2d31f122a..beb4b99ee 100644 --- a/src/codegen/dispatch/soroban.rs +++ b/src/codegen/dispatch/soroban.rs @@ -102,11 +102,8 @@ pub fn function_dispatch( wrapper_cfg.add(&mut vartab, placeholder); -<<<<<<< HEAD if value.len() == 1 { -======= ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f // set the msb 8 bits of the return value to 6, the return value is 64 bits. // FIXME: this assumes that the solidity function always returns one value. let shifted = Expression::ShiftLeft { @@ -136,7 +133,6 @@ pub fn function_dispatch( }; wrapper_cfg.add(&mut vartab, Instr::Return { value: vec![added] }); -<<<<<<< HEAD } else { // return 2 as numberliteral @@ -149,8 +145,6 @@ pub fn function_dispatch( wrapper_cfg.add(&mut vartab, Instr::Return { value: vec![two] }); } -======= ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f vartab.finalize(ns, &mut wrapper_cfg); cfg.public = false; diff --git a/src/emit/expression.rs b/src/emit/expression.rs index 600cfee51..741ea51a4 100644 --- a/src/emit/expression.rs +++ b/src/emit/expression.rs @@ -17,6 +17,7 @@ use inkwell::{AddressSpace, IntPredicate}; use num_bigint::Sign; use num_traits::ToPrimitive; use std::collections::HashMap; +use std::ops::Deref; /// The expression function recursively emits code for expressions. The BasicEnumValue it /// returns depends on the context; if it is simple integer, bool or bytes32 expression, the value @@ -1198,6 +1199,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>( expr, .. } => { + println!("bytes cast"); let e = expression(target, bin, expr, vartab, function, ns).into_int_value(); let size = e.get_type().get_bit_width() / 8; @@ -1538,6 +1540,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>( initializer, .. } => { + + println!("alloc dynamic bytes"); + println!("TYYY {:?}", ty); + println!("SIZE {:?}", size); if matches!(ty, Type::Slice(_)) { let init = initializer.as_ref().unwrap(); @@ -1553,7 +1559,33 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>( .into(), ]) .into() - } else { + } else if matches!(size.clone().deref(), Expression::NumberLiteral{loc, ty, value}) { + + println!("size is number literal"); + let size = expression(target, bin, size, vartab, function, ns).into_int_value(); + + println!("size {:?}", size); + + // convert size to i64 + + let size = size.const_cast(bin.context.i64_type(), false); + + //let elem_size = bin.context.i32_type().const_int(1, false); + + // elem_size.into() + + //bin.vector_new(size, elem_size, initializer.as_ref()).into() + + size.into() + } + + + + + else + + + { let elem = match ty { Type::Slice(_) | Type::String | Type::DynamicBytes => Type::Bytes(1), _ => ty.array_elem(), diff --git a/src/emit/instructions.rs b/src/emit/instructions.rs index c36b266b3..fda1aafec 100644 --- a/src/emit/instructions.rs +++ b/src/emit/instructions.rs @@ -446,6 +446,8 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>( Instr::Print { expr } => { let expr = expression(target, bin, expr, &w.vars, function, ns); + println!("PRINTING {:?}", expr); + target.print(bin, bin.vector_bytes(expr), bin.vector_len(expr)); } Instr::Call { diff --git a/src/emit/soroban/mod.rs b/src/emit/soroban/mod.rs index a8ff9c699..91fd3f203 100644 --- a/src/emit/soroban/mod.rs +++ b/src/emit/soroban/mod.rs @@ -22,10 +22,7 @@ use std::sync; const SOROBAN_ENV_INTERFACE_VERSION: u64 = 90194313216; pub const PUT_CONTRACT_DATA: &str = "l._"; pub const GET_CONTRACT_DATA: &str = "l.1"; -<<<<<<< HEAD pub const LOG_FROM_LINEAR_MEMORY: &str = "x._"; -======= ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f pub struct SorobanTarget; @@ -235,27 +232,21 @@ impl SorobanTarget { .i64_type() .fn_type(&[ty.into(), ty.into()], false); -<<<<<<< HEAD let log_function_ty = binary .context .i64_type() .fn_type(&[ty.into(), ty.into(), ty.into(), ty.into()], false); -======= ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f binary .module .add_function(PUT_CONTRACT_DATA, function_ty_1, Some(Linkage::External)); binary .module .add_function(GET_CONTRACT_DATA, function_ty, Some(Linkage::External)); -<<<<<<< HEAD binary .module .add_function(LOG_FROM_LINEAR_MEMORY, log_function_ty, Some(Linkage::External)); -======= ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f } fn emit_initializer(binary: &mut Binary, _ns: &ast::Namespace) { diff --git a/src/emit/soroban/target.rs b/src/emit/soroban/target.rs index 7ee0a5099..2c65416e6 100644 --- a/src/emit/soroban/target.rs +++ b/src/emit/soroban/target.rs @@ -2,13 +2,8 @@ use crate::codegen::cfg::HashTy; use crate::codegen::Expression; -<<<<<<< HEAD use crate::emit::binary::{self, Binary}; use crate::emit::soroban::{SorobanTarget, GET_CONTRACT_DATA, LOG_FROM_LINEAR_MEMORY, PUT_CONTRACT_DATA}; -======= -use crate::emit::binary::Binary; -use crate::emit::soroban::{SorobanTarget, GET_CONTRACT_DATA, PUT_CONTRACT_DATA}; ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f use crate::emit::ContractArgs; use crate::emit::{TargetRuntime, Variable}; use crate::emit_context; @@ -18,17 +13,10 @@ use crate::sema::ast::{Function, Namespace, Type}; use inkwell::types::{BasicTypeEnum, IntType}; use inkwell::values::{ -<<<<<<< HEAD AnyValue, ArrayValue, AsValueRef, BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue }; use inkwell::AddressSpace; -======= - ArrayValue, BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, IntValue, - PointerValue, -}; - ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f use solang_parser::pt::Loc; use std::collections::HashMap; @@ -248,22 +236,15 @@ impl<'a> TargetRuntime<'a> for SorobanTarget { /// Prints a string /// TODO: Implement this function, with a call to the `log` function in the Soroban runtime. -<<<<<<< HEAD fn print(&self, bin: &Binary, string: PointerValue, length: IntValue) { + if string.is_const() { - let mut toprint; - unsafe { - toprint = string.as_value_ref().offset(0); - println!( "TO PRINT! {:?}", toprint); - } - //println!("print called with string: {:?} ", string.as_value_ref()); println!("msg_pos: {:?}", string); println!("length: {:?}", length); let msg_pos = bin.builder.build_ptr_to_int(string, bin.context.i64_type(), "msg_pos").unwrap(); - let msg_pos = msg_pos.const_cast(bin.context.i64_type(), false); @@ -271,12 +252,60 @@ impl<'a> TargetRuntime<'a> for SorobanTarget { println!("msg_pos extracted: {:?}", msg_pos); println!("============================================================="); + let length = length.const_cast(bin.context.i64_type(), false); + + + let eight = bin.context.i64_type().const_int(8, false); + let four = bin.context.i64_type().const_int(4, false); + let zero = bin.context.i64_type().const_int(0, false); + let thirty_two = bin.context.i64_type().const_int(32, false); + + // encode msg_pos and length + let msg_pos_encoded = bin.builder.build_left_shift(msg_pos, thirty_two, "temp").unwrap(); + let msg_pos_encoded = bin.builder.build_int_add(msg_pos_encoded, four, "msg_pos_encoded").unwrap(); + + + let length_encoded = bin.builder.build_left_shift(length, thirty_two, "temp").unwrap(); + let length_encoded = bin.builder.build_int_add(length_encoded, four, "length_encoded").unwrap(); + + + let zero_encoded = bin.builder.build_left_shift(zero, eight, "temp").unwrap(); - //let length = bin.context.i64_type().const_int(1024, false); + let eight_encoded = bin.builder.build_left_shift(eight, eight, "temp").unwrap(); + let eight_encoded = bin.builder.build_int_add(eight_encoded, four, "eight_encoded").unwrap(); + - let length = length.const_cast(bin.context.i64_type(), false); + + + let call_res = bin.builder.build_call( + bin.module.get_function(LOG_FROM_LINEAR_MEMORY).unwrap(), + &[ + msg_pos_encoded.into(), + length_encoded.into(), + msg_pos_encoded.into(), + four.into(), + ], + "log", + ).unwrap(); + } + + else { + + + /*println!("msg_pos: {:?}", string); + println!("length: {:?}", length); + + let msg_pos = bin.builder.build_ptr_to_int(string, bin.context.i64_type(), "msg_pos").unwrap(); + //let msg_pos = msg_pos.const_cast(bin.context.i64_type(), false); + + + + println!("msg_pos extracted: {:?}", msg_pos); + println!("============================================================="); + + //let length = length.const_cast(bin.context.i64_type(), false); let eight = bin.context.i64_type().const_int(8, false); @@ -288,11 +317,24 @@ impl<'a> TargetRuntime<'a> for SorobanTarget { let msg_pos_encoded = bin.builder.build_left_shift(msg_pos, thirty_two, "temp").unwrap(); let msg_pos_encoded = bin.builder.build_int_add(msg_pos_encoded, four, "msg_pos_encoded").unwrap(); + println!("CAN MSG ENCODE"); + + + //let length = bin.builder.build_int_z_extend(length, bin.context.i64_type(), "extended").unwrap(); + + + let length_type = length.get_type(); + println!("LENGTH TYPE: {:?}", length_type); + + //let length = bin.builder.build_int_z_extend(length, bin.context.i64_type(), "extended").unwrap(); + //let length = bin.builder.build_int_cast(length, bin.context.i64_type(), "extended").unwrap(); let length_encoded = bin.builder.build_left_shift(length, thirty_two, "temp").unwrap(); let length_encoded = bin.builder.build_int_add(length_encoded, four, "length_encoded").unwrap(); + println!("CAN LENGTH ENCODE"); + let zero_encoded = bin.builder.build_left_shift(zero, eight, "temp").unwrap(); @@ -313,11 +355,12 @@ impl<'a> TargetRuntime<'a> for SorobanTarget { ], "log", ).unwrap(); + */ + + + } } -======= - fn print(&self, bin: &Binary, string: PointerValue, length: IntValue) {} ->>>>>>> 06798cdeac6fd62ee98f5ae7da38f3af4933dc0f /// Return success without any result fn return_empty_abi(&self, bin: &Binary) { diff --git a/src/emit/strings.rs b/src/emit/strings.rs index 59bfb3803..3c7b1a0ef 100644 --- a/src/emit/strings.rs +++ b/src/emit/strings.rs @@ -19,6 +19,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>( function: FunctionValue<'a>, ns: &Namespace, ) -> BasicValueEnum<'a> { + + + println!("IN format_string"); + // first we need to calculate the space we need let mut length = bin.context.i32_type().const_zero();