소스 검색

Add casting from bytes to slice(bytes1)

This makes it possible to pass variables into create_program_address()

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 년 전
부모
커밋
9e2fd98d87
3개의 변경된 파일49개의 추가작업 그리고 1개의 파일을 삭제
  1. 18 0
      src/emit/mod.rs
  2. 6 1
      src/sema/expression.rs
  3. 25 0
      tests/solana_tests/builtin.rs

+ 18 - 0
src/emit/mod.rs

@@ -3248,6 +3248,24 @@ pub trait TargetRuntime<'a> {
                     "ptr_to_int",
                     "ptr_to_int",
                 )
                 )
                 .into()
                 .into()
+        } else if matches!((from, to), (Type::DynamicBytes, Type::Slice(_))) {
+            let slice = bin.build_alloca(function, bin.llvm_type(to, ns), "slice");
+
+            let data = bin.vector_bytes(val);
+
+            let data_ptr = bin.builder.build_struct_gep(slice, 0, "data").unwrap();
+
+            bin.builder.build_store(data_ptr, data);
+
+            let len =
+                bin.builder
+                    .build_int_z_extend(bin.vector_len(val), bin.context.i64_type(), "len");
+
+            let len_ptr = bin.builder.build_struct_gep(slice, 1, "len").unwrap();
+
+            bin.builder.build_store(len_ptr, len);
+
+            bin.builder.build_load(slice, "slice")
         } else {
         } else {
             val
             val
         }
         }

+ 6 - 1
src/sema/expression.rs

@@ -1072,6 +1072,9 @@ impl Expression {
             {
             {
                 Ok(self.clone())
                 Ok(self.clone())
             }
             }
+            (Type::DynamicBytes, Type::Slice(ty)) if ty.as_ref() == &Type::Bytes(1) => {
+                Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
+            }
             _ => {
             _ => {
                 diagnostics.push(Diagnostic::cast_error(
                 diagnostics.push(Diagnostic::cast_error(
                     *loc,
                     *loc,
@@ -6941,7 +6944,7 @@ fn array_literal(
 
 
     // We follow the solidity scheme were everthing gets implicitly converted to the
     // We follow the solidity scheme were everthing gets implicitly converted to the
     // type of the first element
     // type of the first element
-    let first = expression(
+    let mut first = expression(
         flattened.next().unwrap(),
         flattened.next().unwrap(),
         context,
         context,
         ns,
         ns,
@@ -6951,6 +6954,8 @@ fn array_literal(
     )?;
     )?;
 
 
     let ty = if let ResolveTo::Type(ty) = resolve_to {
     let ty = if let ResolveTo::Type(ty) = resolve_to {
+        first = first.cast(&first.loc(), ty, true, ns, diagnostics)?;
+
         ty.clone()
         ty.clone()
     } else {
     } else {
         first.ty()
         first.ty()

+ 25 - 0
tests/solana_tests/builtin.rs

@@ -82,6 +82,12 @@ fn pda() {
 
 
                 return create_program_address(["Talking", "Squirrels"], program_id);
                 return create_program_address(["Talking", "Squirrels"], program_id);
             }
             }
+
+            function create_pda2(bytes a, bytes b) public returns (address) {
+                address program_id = address"BPFLoaderUpgradeab1e11111111111111111111111";
+
+                return create_program_address([a, b], program_id);
+            }
         }"#,
         }"#,
     );
     );
 
 
@@ -97,4 +103,23 @@ fn pda() {
     } else {
     } else {
         panic!("{:?} not expected", returns);
         panic!("{:?} not expected", returns);
     }
     }
+
+    let returns = vm.function(
+        "create_pda2",
+        &[
+            Token::Bytes(b"Talking".to_vec()),
+            Token::Bytes(b"Squirrels".to_vec()),
+        ],
+        &[],
+        None,
+    );
+
+    if let Token::FixedBytes(bs) = &returns[0] {
+        assert_eq!(
+            bs.to_base58(),
+            "2fnQrngrQT4SeLcdToJAD96phoEjNL2man2kfRLCASVk"
+        );
+    } else {
+        panic!("{:?} not expected", returns);
+    }
 }
 }