Parcourir la source

Allow fixed-type structs and arrays to be specified as call() arguments

This allows a struct to be used to encode the arguments to e.g.
spl-token.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young il y a 3 ans
Parent
commit
fd1862ac99
3 fichiers modifiés avec 88 ajouts et 15 suppressions
  1. 17 2
      src/emit/mod.rs
  2. 51 11
      src/emit/solana.rs
  3. 20 2
      src/sema/expression.rs

+ 17 - 2
src/emit/mod.rs

@@ -4130,6 +4130,7 @@ pub trait TargetRuntime<'a> {
                         let value = self
                             .expression(bin, value, &w.vars, function, ns)
                             .into_int_value();
+                        let payload_ty = payload.ty();
                         let payload = self.expression(bin, payload, &w.vars, function, ns);
 
                         let address = if let Some(address) = address {
@@ -4182,12 +4183,26 @@ pub trait TargetRuntime<'a> {
                             None => None,
                         };
 
+                        let (payload_ptr, payload_len) = if payload_ty == Type::DynamicBytes {
+                            (bin.vector_bytes(payload), bin.vector_len(payload))
+                        } else {
+                            let ptr = payload.into_pointer_value();
+                            let len = ptr
+                                .get_type()
+                                .get_element_type()
+                                .size_of()
+                                .unwrap()
+                                .const_cast(bin.context.i32_type(), false);
+
+                            (ptr, len)
+                        };
+
                         self.external_call(
                             bin,
                             function,
                             success,
-                            bin.vector_bytes(payload),
-                            bin.vector_len(payload),
+                            payload_ptr,
+                            payload_len,
                             address,
                             gas,
                             value,

+ 51 - 11
src/emit/solana.rs

@@ -2981,7 +2981,15 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .builder
                     .build_struct_gep(instruction, 0, "program_id")
                     .unwrap(),
-                address,
+                binary.builder.build_pointer_cast(
+                    address,
+                    binary
+                        .module
+                        .get_struct_type("struct.SolPubkey")
+                        .unwrap()
+                        .ptr_type(AddressSpace::Generic),
+                    "SolPubkey",
+                ),
             );
 
             let (accounts, accounts_len) = accounts.unwrap();
@@ -2991,7 +2999,15 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .builder
                     .build_struct_gep(instruction, 1, "accounts")
                     .unwrap(),
-                accounts,
+                binary.builder.build_pointer_cast(
+                    accounts,
+                    binary
+                        .module
+                        .get_struct_type("struct.SolAccountMeta")
+                        .unwrap()
+                        .ptr_type(AddressSpace::Generic),
+                    "SolAccountMeta",
+                ),
             );
 
             binary.builder.build_store(
@@ -2999,7 +3015,11 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .builder
                     .build_struct_gep(instruction, 2, "accounts_len")
                     .unwrap(),
-                accounts_len,
+                binary.builder.build_int_z_extend(
+                    accounts_len,
+                    binary.context.i64_type(),
+                    "accounts_len",
+                ),
             );
 
             binary.builder.build_store(
@@ -3007,7 +3027,11 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .builder
                     .build_struct_gep(instruction, 3, "data")
                     .unwrap(),
-                payload,
+                binary.builder.build_pointer_cast(
+                    payload,
+                    binary.context.i8_type().ptr_type(AddressSpace::Generic),
+                    "data",
+                ),
             );
 
             binary.builder.build_store(
@@ -3015,25 +3039,41 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .builder
                     .build_struct_gep(instruction, 4, "data_len")
                     .unwrap(),
-                payload_len,
+                binary.builder.build_int_z_extend(
+                    payload_len,
+                    binary.context.i64_type(),
+                    "payload_len",
+                ),
             );
 
             let parameters = self.sol_parameters(binary);
 
-            let account_infos = binary.builder.build_load(
+            let account_infos = binary.builder.build_pointer_cast(
                 binary
                     .builder
                     .build_struct_gep(parameters, 0, "ka")
                     .unwrap(),
-                "ka",
+                binary
+                    .module
+                    .get_struct_type("struct.SolAccountInfo")
+                    .unwrap()
+                    .ptr_type(AddressSpace::Generic),
+                "SolAccountInfo",
             );
 
-            let account_infos_len = binary.builder.build_load(
+            let account_infos_len = binary.builder.build_int_truncate(
                 binary
                     .builder
-                    .build_struct_gep(parameters, 0, "ka")
-                    .unwrap(),
-                "ka",
+                    .build_load(
+                        binary
+                            .builder
+                            .build_struct_gep(parameters, 1, "ka_num")
+                            .unwrap(),
+                        "ka_num",
+                    )
+                    .into_int_value(),
+                binary.context.i32_type(),
+                "ka_num",
             );
 
             let external_call = binary.module.get_function("sol_invoke_signed_c").unwrap();

+ 20 - 2
src/sema/expression.rs

@@ -6235,7 +6235,7 @@ fn method_call_pos_args(
                 return Err(());
             }
 
-            let expr = expression(
+            let args = expression(
                 &args[0],
                 context,
                 ns,
@@ -6244,7 +6244,25 @@ fn method_call_pos_args(
                 ResolveTo::Type(&Type::DynamicBytes),
             )?;
 
-            let args = expr.cast(&args[0].loc(), &Type::DynamicBytes, true, ns, diagnostics)?;
+            let mut args_ty = args.ty();
+
+            match args_ty.deref_any() {
+                Type::DynamicBytes => (),
+                Type::Bytes(_) => {
+                    args_ty = Type::DynamicBytes;
+                }
+                Type::Array(..) | Type::Struct(..) if !args_ty.is_dynamic(ns) => (),
+                _ => {
+                    diagnostics.push(Diagnostic::error(
+                        args.loc(),
+                        format!("‘{}’ is not fixed length type", args_ty.to_string(ns),),
+                    ));
+
+                    return Err(());
+                }
+            }
+
+            let args = args.cast(&args.loc(), args_ty.deref_any(), true, ns, diagnostics)?;
 
             return Ok(Expression::ExternalFunctionCallRaw {
                 loc: *loc,