diff --git a/.github/workflows/smartir_test.yml b/.github/workflows/smartir_test.yml index df730b5..da77579 100644 --- a/.github/workflows/smartir_test.yml +++ b/.github/workflows/smartir_test.yml @@ -17,12 +17,12 @@ jobs: - name: Code format check working-directory: ./ir_cli run: | - rustup default 1.67 + rustup default 1.70 make fmt-check shell: bash - name: e2e tests working-directory: ./ir_cli shell: bash run: | - rustup default 1.67 + rustup default 1.70 make test \ No newline at end of file diff --git a/docker/ir-cli-builder/Dockerfile b/docker/ir-cli-builder/Dockerfile index 9009577..5662a6b 100644 --- a/docker/ir-cli-builder/Dockerfile +++ b/docker/ir-cli-builder/Dockerfile @@ -50,6 +50,8 @@ RUN yum install -y bison #RUN source /opt/rh/devtoolset-11/enable RUN yum install -y gcc-c++ RUN yum install -y gcc-toolset-11 gcc-toolset-11-gcc-c++ gcc-toolset-11-make gcc-toolset-11-libasan-devel gcc-toolset-11-gdb gcc-toolset-11-binutils +RUN echo "source /opt/rh/gcc-toolset-11/enable" >> /etc/bashrc +SHELL ["/bin/bash", "--login", "-c"] RUN mkdir -p /opt WORKDIR /opt # COPY linux-x64/clang+llvm-14.0.6-x86_64-linux-gnu-rhel-8.4.tar.xz /opt/ diff --git a/ir_cli/Cargo.lock b/ir_cli/Cargo.lock index 30d18fa..96a61fd 100644 --- a/ir_cli/Cargo.lock +++ b/ir_cli/Cargo.lock @@ -883,20 +883,20 @@ dependencies = [ [[package]] name = "inkwell" version = "0.2.0" -source = "git+https://github.com/TheDan64/inkwell?rev=bbe1f3d76c45fc137a125665861fc6382ab352d6#bbe1f3d76c45fc137a125665861fc6382ab352d6" +source = "git+https://github.com/TheDan64/inkwell#0b2cde9394320ab6f097ef10408d663a28d44be3" dependencies = [ "either", "inkwell_internals", "libc", "llvm-sys", "once_cell", - "parking_lot", + "thiserror", ] [[package]] name = "inkwell_internals" version = "0.8.0" -source = "git+https://github.com/TheDan64/inkwell?rev=bbe1f3d76c45fc137a125665861fc6382ab352d6#bbe1f3d76c45fc137a125665861fc6382ab352d6" +source = "git+https://github.com/TheDan64/inkwell#0b2cde9394320ab6f097ef10408d663a28d44be3" dependencies = [ "proc-macro2", "quote", @@ -1137,9 +1137,9 @@ checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "llvm-sys" -version = "140.1.2" +version = "150.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b285f8682531b9b394dd9891977a2a28c47006e491bda944e1ca62ebab2664" +checksum = "bfd60e740af945d99c2446a52e3ab8cdba2f740a40a16c51f6871bdea2abc687" dependencies = [ "cc", "lazy_static", diff --git a/ir_cli/Cargo.toml b/ir_cli/Cargo.toml index c24e22e..2ee088a 100644 --- a/ir_cli/Cargo.toml +++ b/ir_cli/Cargo.toml @@ -18,8 +18,8 @@ num-traits = "0.2.17" num-derive = "0.4.1" rustc-serialize = "0.3.24" bstr = "1.7.0" -lalrpop ="0.19.9" -lalrpop-util ="0.19.9" +lalrpop = "0.19.9" +lalrpop-util = "0.19.9" rust-crypto = "^0.2" rsa = "0.3.0" keccak-hash = "0.10.0" @@ -30,7 +30,10 @@ hex = "0.4.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_derive = { version = "1.0" } -inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "bbe1f3d76c45fc137a125665861fc6382ab352d6", features = ["target-webassembly", "llvm14-0-force-static"] } +inkwell = { git = "https://github.com/TheDan64/inkwell", features = [ + "target-webassembly", + "llvm15-0-force-static", +] } smart_ir_macro = { path = "../smart_ir_macro", version = "0.3.0" } smart_ir = { path = "../smart_ir" } compiler_base_span = "0.0.1" diff --git a/smart_ir/Cargo.lock b/smart_ir/Cargo.lock index edcdeaf..beb0ce5 100644 --- a/smart_ir/Cargo.lock +++ b/smart_ir/Cargo.lock @@ -828,20 +828,20 @@ dependencies = [ [[package]] name = "inkwell" version = "0.2.0" -source = "git+https://github.com/TheDan64/inkwell?rev=bbe1f3d76c45fc137a125665861fc6382ab352d6#bbe1f3d76c45fc137a125665861fc6382ab352d6" +source = "git+https://github.com/TheDan64/inkwell#0b2cde9394320ab6f097ef10408d663a28d44be3" dependencies = [ "either", "inkwell_internals", "libc", "llvm-sys", "once_cell", - "parking_lot", + "thiserror", ] [[package]] name = "inkwell_internals" version = "0.8.0" -source = "git+https://github.com/TheDan64/inkwell?rev=bbe1f3d76c45fc137a125665861fc6382ab352d6#bbe1f3d76c45fc137a125665861fc6382ab352d6" +source = "git+https://github.com/TheDan64/inkwell#0b2cde9394320ab6f097ef10408d663a28d44be3" dependencies = [ "proc-macro2", "quote", @@ -1049,9 +1049,9 @@ checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "llvm-sys" -version = "140.1.2" +version = "150.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b285f8682531b9b394dd9891977a2a28c47006e491bda944e1ca62ebab2664" +checksum = "bfd60e740af945d99c2446a52e3ab8cdba2f740a40a16c51f6871bdea2abc687" dependencies = [ "cc", "lazy_static", diff --git a/smart_ir/Cargo.toml b/smart_ir/Cargo.toml index da9ae4d..88161b4 100644 --- a/smart_ir/Cargo.toml +++ b/smart_ir/Cargo.toml @@ -17,9 +17,9 @@ indexmap = "1.0" lalrpop-util = { version = "0.20.0", features = ["lexer"] } downcast-rs = "1.2.0" smart_ir_macro = { path = "../smart_ir_macro", version = "0.3.0" } -inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "bbe1f3d76c45fc137a125665861fc6382ab352d6", features = [ +inkwell = { git = "https://github.com/TheDan64/inkwell", features = [ "target-webassembly", - "llvm14-0-force-static", + "llvm15-0-force-static", ] } num-bigint = "0.4" num-integer = "0.1.45" diff --git a/smart_ir/src/abi/params.rs b/smart_ir/src/abi/params.rs index 67c35dd..0bf2d07 100644 --- a/smart_ir/src/abi/params.rs +++ b/smart_ir/src/abi/params.rs @@ -5,6 +5,7 @@ #[allow(unused_imports)] use anyhow::{anyhow, Result}; use nano_leb128::ULEB128; +use num_bigint::BigInt; #[allow(unused_imports)] use num_traits::FromPrimitive; use std::collections::HashMap; @@ -30,6 +31,8 @@ pub enum ABIParam { I64(i64), U128(u128), I128(i128), + U256(BigInt), + I256(BigInt), Bool(bool), Str(String), Parampack(Vec), @@ -45,6 +48,8 @@ pub enum ABIParam { I64Array(Vec), U128Array(Vec), I128Array(Vec), + U256Array(Vec), + I256Array(Vec), BoolArray(Vec), StrArray(Vec), @@ -59,6 +64,8 @@ pub enum ABIParam { StrI64Map(HashMap), StrU128Map(HashMap), StrI128Map(HashMap), + StrU256Map(HashMap), + StrI256Map(HashMap), StrBoolMap(HashMap), StrStrMap(HashMap), } @@ -157,6 +164,8 @@ impl ABIParam { ABIParam::I64(v) => (*v).to_le_bytes().to_vec(), ABIParam::U128(v) => (*v).to_le_bytes().to_vec(), ABIParam::I128(v) => (*v).to_le_bytes().to_vec(), + ABIParam::U256(v) => (*v).to_bytes_le().1.to_vec(), + ABIParam::I256(v) => (*v).to_bytes_le().1.to_vec(), ABIParam::Bool(v) => vec![(*v) as u8], ABIParam::Str(v) => { let mut buf = buffer_starts_with_uleb128_len(v.len()); @@ -173,6 +182,8 @@ impl ABIParam { ABIParam::I64Array(v) => encode_vec!(v, I64), ABIParam::U128Array(v) => encode_vec!(v, U128), ABIParam::I128Array(v) => encode_vec!(v, I128), + ABIParam::U256Array(v) => encode_vec!(v, U256), + ABIParam::I256Array(v) => encode_vec!(v, I256), ABIParam::BoolArray(v) => encode_vec!(v, Bool), ABIParam::StrArray(v) => encode_vec!(v, Str), ABIParam::StrU8Map(v) => encode_map!(v, Str, U8), @@ -185,6 +196,8 @@ impl ABIParam { ABIParam::StrI64Map(v) => encode_map!(v, Str, I64), ABIParam::StrU128Map(v) => encode_map!(v, Str, U128), ABIParam::StrI128Map(v) => encode_map!(v, Str, I128), + ABIParam::StrU256Map(v) => encode_map!(v, Str, U256), + ABIParam::StrI256Map(v) => encode_map!(v, Str, I256), ABIParam::StrBoolMap(v) => encode_map!(v, Str, Bool), ABIParam::StrStrMap(v) => encode_map!(v, Str, Str), ABIParam::Parampack(v) => { @@ -207,6 +220,8 @@ impl ABIParam { ABIParam::I64(_) => ParamType::I64, ABIParam::U128(_) => ParamType::U128, ABIParam::I128(_) => ParamType::I128, + ABIParam::U256(_) => ParamType::U256, + ABIParam::I256(_) => ParamType::I256, ABIParam::Bool(_) => ParamType::Bool, ABIParam::Str(_) => ParamType::Str, ABIParam::Parampack(_) => ParamType::Parampack, @@ -220,6 +235,8 @@ impl ABIParam { ABIParam::I64Array(_) => ParamType::I64Array, ABIParam::U128Array(_) => ParamType::U128Array, ABIParam::I128Array(_) => ParamType::I128Array, + ABIParam::U256Array(_) => ParamType::U256Array, + ABIParam::I256Array(_) => ParamType::I256Array, ABIParam::BoolArray(_) => ParamType::BoolArray, ABIParam::StrArray(_) => ParamType::StrArray, ABIParam::StrU8Map(_) => ParamType::StrU8Map, @@ -232,6 +249,8 @@ impl ABIParam { ABIParam::StrI64Map(_) => ParamType::StrI64Map, ABIParam::StrU128Map(_) => ParamType::StrU128Map, ABIParam::StrI128Map(_) => ParamType::StrI128Map, + ABIParam::StrU256Map(_) => ParamType::StrU256Map, + ABIParam::StrI256Map(_) => ParamType::StrI256Map, ABIParam::StrBoolMap(_) => ParamType::StrBoolMap, ABIParam::StrStrMap(_) => ParamType::StrStrMap, } @@ -280,6 +299,21 @@ pub fn decode_param( ParamType::I64 => decode_int!(data, offset, I64, i64, 8), ParamType::U128 => decode_int!(data, offset, U128, u128, 16), ParamType::I128 => decode_int!(data, offset, I128, i128, 16), + ParamType::U256 => { + const SIZE: usize = 32; + let bytes = get_bytes::(data, offset); + let param = ABIParam::U256(BigInt::from_bytes_be(num_bigint::Sign::NoSign, &bytes)); + *offset += SIZE; + Ok(param) + } + ParamType::I256 => { + const SIZE: usize = 32; + let bytes = get_bytes::(data, offset); + let param = ABIParam::I256(BigInt::from_bytes_be(num_bigint::Sign::NoSign, &bytes)); + *offset += SIZE; + Ok(param) + } + ParamType::Bool => { let param = ABIParam::Bool(data[*offset] != 0); *offset += 1; @@ -301,6 +335,8 @@ pub fn decode_param( ParamType::I64Array => decode_vec!(data, offset, I64, I64Array), ParamType::U128Array => decode_vec!(data, offset, U128, U128Array), ParamType::I128Array => decode_vec!(data, offset, I128, I128Array), + ParamType::U256Array => decode_vec!(data, offset, U256, U256Array), + ParamType::I256Array => decode_vec!(data, offset, I256, I256Array), ParamType::BoolArray => decode_vec!(data, offset, Bool, BoolArray), ParamType::StrArray => decode_vec!(data, offset, Str, StrArray), ParamType::StrU8Map => decode_map!(data, offset, Str, U8, StrU8Map), @@ -313,6 +349,8 @@ pub fn decode_param( ParamType::StrI64Map => decode_map!(data, offset, Str, I64, StrI64Map), ParamType::StrU128Map => decode_map!(data, offset, Str, U128, StrU128Map), ParamType::StrI128Map => decode_map!(data, offset, Str, I128, StrI128Map), + ParamType::StrU256Map => decode_map!(data, offset, Str, U256, StrU256Map), + ParamType::StrI256Map => decode_map!(data, offset, Str, I256, StrI256Map), ParamType::StrBoolMap => decode_map!(data, offset, Str, Bool, StrBoolMap), ParamType::StrStrMap => decode_map!(data, offset, Str, Str, StrStrMap), ParamType::Parampack => unimplemented!(), diff --git a/smart_ir/src/encoding/datastream/mod.rs b/smart_ir/src/encoding/datastream/mod.rs index 16ff414..b5c5ada 100644 --- a/smart_ir/src/encoding/datastream/mod.rs +++ b/smart_ir/src/encoding/datastream/mod.rs @@ -22,9 +22,11 @@ pub enum ParamType { I64 = 7, U128 = 8, I128 = 9, - Bool = 10, - Str = 11, - Parampack = 12, + U256 = 10, + I256 = 11, + Bool = 12, + Str = 13, + Parampack = 14, // Array params U8Array = 32, @@ -37,8 +39,10 @@ pub enum ParamType { I64Array = 39, U128Array = 40, I128Array = 41, - BoolArray = 42, - StrArray = 43, + U256Array = 42, + I256Array = 43, + BoolArray = 44, + StrArray = 45, // Map params StrU8Map = 64, @@ -51,8 +55,10 @@ pub enum ParamType { StrI64Map = 71, StrU128Map = 72, StrI128Map = 73, - StrBoolMap = 74, - StrStrMap = 75, + StrU256Map = 74, + StrI256Map = 75, + StrBoolMap = 76, + StrStrMap = 77, } impl ParamType { @@ -96,11 +102,13 @@ impl TryInto for cfg::Type { cfg::IntType::I32 => Ok(ParamType::I32), cfg::IntType::I64 => Ok(ParamType::I64), cfg::IntType::I128 => Ok(ParamType::I128), + cfg::IntType::I256 => Ok(ParamType::I256), cfg::IntType::U8 => Ok(ParamType::U8), cfg::IntType::U16 => Ok(ParamType::U16), cfg::IntType::U32 => Ok(ParamType::U32), cfg::IntType::U64 => Ok(ParamType::U64), cfg::IntType::U128 => Ok(ParamType::U128), + cfg::IntType::U256 => Ok(ParamType::U256), }, }, cfg::Type::Map { key, value } => { @@ -116,11 +124,13 @@ impl TryInto for cfg::Type { cfg::IntType::I32 => Ok(ParamType::StrI32Map), cfg::IntType::I64 => Ok(ParamType::StrI64Map), cfg::IntType::I128 => Ok(ParamType::StrI128Map), + cfg::IntType::I256 => Ok(ParamType::StrI256Map), cfg::IntType::U8 => Ok(ParamType::StrU8Map), cfg::IntType::U16 => Ok(ParamType::StrU16Map), cfg::IntType::U32 => Ok(ParamType::StrU32Map), cfg::IntType::U64 => Ok(ParamType::StrU64Map), cfg::IntType::U128 => Ok(ParamType::StrU128Map), + cfg::IntType::U256 => Ok(ParamType::StrU256Map), }, }, _ => err, @@ -140,11 +150,13 @@ impl TryInto for cfg::Type { cfg::IntType::I32 => Ok(ParamType::I32Array), cfg::IntType::I64 => Ok(ParamType::I64Array), cfg::IntType::I128 => Ok(ParamType::I128Array), + cfg::IntType::I256 => Ok(ParamType::I256Array), cfg::IntType::U8 => Ok(ParamType::U8Array), cfg::IntType::U16 => Ok(ParamType::U16Array), cfg::IntType::U32 => Ok(ParamType::U32Array), cfg::IntType::U64 => Ok(ParamType::U64Array), cfg::IntType::U128 => Ok(ParamType::U128Array), + cfg::IntType::U256 => Ok(ParamType::U256Array), }, }, _ => err, diff --git a/smart_ir/src/ir/cfg.rs b/smart_ir/src/ir/cfg.rs index 13c8a80..fb19174 100644 --- a/smart_ir/src/ir/cfg.rs +++ b/smart_ir/src/ir/cfg.rs @@ -7,6 +7,7 @@ use std::{fmt::Display, rc::Rc}; use crate::ir::interface_type::PartialFuncName; use core::hash::Hash; use indexmap::IndexMap; +use num_bigint::BigInt; use smart_ir_macro::MetaDataNode; use super::builder::{BasicBlockId, IdentifierId, MetaDataId}; @@ -58,11 +59,13 @@ pub enum IntLiteral { I32(i32), I64(i64), I128(i128), + I256(BigInt), U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), + U256(BigInt), } impl Display for Literal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -75,11 +78,13 @@ impl Display for Literal { IntLiteral::I32(val) => write!(f, "{val}"), IntLiteral::I64(val) => write!(f, "{val}"), IntLiteral::I128(val) => write!(f, "{val}"), + IntLiteral::I256(val) => write!(f, "{val}"), IntLiteral::U8(val) => write!(f, "{val}"), IntLiteral::U16(val) => write!(f, "{val}"), IntLiteral::U32(val) => write!(f, "{val}"), IntLiteral::U64(val) => write!(f, "{val}"), IntLiteral::U128(val) => write!(f, "{val}"), + IntLiteral::U256(val) => write!(f, "{val}"), }, } } @@ -96,11 +101,13 @@ impl Literal { IntLiteral::I32(_) => Type::Primitive(PrimitiveType::Int(IntType::I32)), IntLiteral::I64(_) => Type::Primitive(PrimitiveType::Int(IntType::I64)), IntLiteral::I128(_) => Type::Primitive(PrimitiveType::Int(IntType::I128)), + IntLiteral::I256(_) => Type::Primitive(PrimitiveType::Int(IntType::I256)), IntLiteral::U8(_) => Type::Primitive(PrimitiveType::Int(IntType::U8)), IntLiteral::U16(_) => Type::Primitive(PrimitiveType::Int(IntType::U16)), IntLiteral::U32(_) => Type::Primitive(PrimitiveType::Int(IntType::U32)), IntLiteral::U64(_) => Type::Primitive(PrimitiveType::Int(IntType::U64)), IntLiteral::U128(_) => Type::Primitive(PrimitiveType::Int(IntType::U128)), + IntLiteral::U256(_) => Type::Primitive(PrimitiveType::Int(IntType::U256)), }, } } @@ -466,11 +473,13 @@ impl Display for Type { IntType::I32 => write!(f, "i32"), IntType::I64 => write!(f, "i64"), IntType::I128 => write!(f, "i128"), + IntType::I256 => write!(f, "i256"), IntType::U8 => write!(f, "u8"), IntType::U16 => write!(f, "u16"), IntType::U32 => write!(f, "u32"), IntType::U64 => write!(f, "u64"), IntType::U128 => write!(f, "u128"), + IntType::U256 => write!(f, "u256"), }, }, Type::Map { key, value } => write!(f, "{{{key}:{value}}}"), @@ -523,11 +532,13 @@ pub enum IntType { I32, I64, I128, + I256, U8, U16, U32, U64, U128, + U256, } #[derive(Clone, Debug, PartialEq, Eq, Default)] diff --git a/smart_ir/src/ir/context.rs b/smart_ir/src/ir/context.rs index 83cbefa..1a700c0 100644 --- a/smart_ir/src/ir/context.rs +++ b/smart_ir/src/ir/context.rs @@ -29,17 +29,19 @@ pub const IR_RUNTIME_U16_TYPE: u8 = 1; pub const IR_RUNTIME_U32_TYPE: u8 = 2; pub const IR_RUNTIME_U64_TYPE: u8 = 3; pub const IR_RUNTIME_U128_TYPE: u8 = 4; -pub const IR_RUNTIME_I8_TYPE: u8 = 5; -pub const IR_RUNTIME_I16_TYPE: u8 = 6; -pub const IR_RUNTIME_I32_TYPE: u8 = 7; -pub const IR_RUNTIME_I64_TYPE: u8 = 8; -pub const IR_RUNTIME_I128_TYPE: u8 = 9; -pub const IR_RUNTIME_BOOL_TYPE: u8 = 10; -pub const IR_RUNTIME_STR_TYPE: u8 = 11; -pub const IR_RUNTIME_ASSET_TYPE: u8 = 12; -pub const IR_RUNTIME_STRUCT_TYPE: u8 = 13; -pub const IR_RUNTIME_ARRAY_TYPE: u8 = 14; -pub const IR_RUNTIME_MAP_TYPE: u8 = 15; +pub const IR_RUNTIME_U256_TYPE: u8 = 5; +pub const IR_RUNTIME_I8_TYPE: u8 = 6; +pub const IR_RUNTIME_I16_TYPE: u8 = 7; +pub const IR_RUNTIME_I32_TYPE: u8 = 8; +pub const IR_RUNTIME_I64_TYPE: u8 = 9; +pub const IR_RUNTIME_I128_TYPE: u8 = 10; +pub const IR_RUNTIME_I256_TYPE: u8 = 5; +pub const IR_RUNTIME_BOOL_TYPE: u8 = 12; +pub const IR_RUNTIME_STR_TYPE: u8 = 13; +pub const IR_RUNTIME_ASSET_TYPE: u8 = 14; +pub const IR_RUNTIME_STRUCT_TYPE: u8 = 15; +pub const IR_RUNTIME_ARRAY_TYPE: u8 = 16; +pub const IR_RUNTIME_MAP_TYPE: u8 = 17; /// AntChain IR IRContext #[derive(Debug, Default, Clone)] @@ -83,11 +85,13 @@ impl IRContext { IntType::I32 => IR_RUNTIME_I32_TYPE, IntType::I64 => IR_RUNTIME_I64_TYPE, IntType::I128 => IR_RUNTIME_I128_TYPE, + IntType::I256 => IR_RUNTIME_I256_TYPE, IntType::U8 => IR_RUNTIME_U8_TYPE, IntType::U16 => IR_RUNTIME_U16_TYPE, IntType::U32 => IR_RUNTIME_U32_TYPE, IntType::U64 => IR_RUNTIME_U64_TYPE, IntType::U128 => IR_RUNTIME_U128_TYPE, + IntType::U256 => IR_RUNTIME_U256_TYPE, }, PrimitiveType::Str => IR_RUNTIME_STR_TYPE, PrimitiveType::Bool => IR_RUNTIME_BOOL_TYPE, diff --git a/smart_ir/src/ir/printer.rs b/smart_ir/src/ir/printer.rs index 47f39df..7908cd4 100644 --- a/smart_ir/src/ir/printer.rs +++ b/smart_ir/src/ir/printer.rs @@ -122,11 +122,13 @@ impl IRPrinter<'_> { IntType::I32 => write!(w, "i32"), IntType::I64 => write!(w, "i64"), IntType::I128 => write!(w, "i128"), + IntType::I256 => write!(w, "i256"), IntType::U8 => write!(w, "u8"), IntType::U16 => write!(w, "u16"), IntType::U32 => write!(w, "u32"), IntType::U64 => write!(w, "u64"), IntType::U128 => write!(w, "u128"), + IntType::U256 => write!(w, "u256"), }, }, Type::Map { key, value } => { @@ -477,11 +479,13 @@ impl IRPrinter<'_> { IntLiteral::I32(val) => write!(w, "{val}: i32"), IntLiteral::I64(val) => write!(w, "{val}: i64"), IntLiteral::I128(val) => write!(w, "{val}: i128"), + IntLiteral::I256(val) => write!(w, "{val}: i256"), IntLiteral::U8(val) => write!(w, "{val}: u8"), IntLiteral::U16(val) => write!(w, "{val}: u16"), IntLiteral::U32(val) => write!(w, "{val}: u32"), IntLiteral::U64(val) => write!(w, "{val}: u64"), IntLiteral::U128(val) => write!(w, "{val}: u128"), + IntLiteral::U256(val) => write!(w, "{val}: u256"), }, } } diff --git a/smart_ir/src/ir_codegen/builtin_constants.rs b/smart_ir/src/ir_codegen/builtin_constants.rs index b6aec4b..9b4eaeb 100644 --- a/smart_ir/src/ir_codegen/builtin_constants.rs +++ b/smart_ir/src/ir_codegen/builtin_constants.rs @@ -13,7 +13,9 @@ pub const Q_VEC_SLICE_FUNC_NAME: &str = "qvector_slice"; pub const Q_MAP_NEW_FUNC_NAME: &str = "qhashtbl"; pub const RUNTIME_CONTEXT_LLVM_TY: &str = "struct.RuntimeContext"; pub const Q_VECTOR_OBJ_S: &str = "struct.qvector_obj_s"; +pub const Q_VECTOR_ITER: &str = "struct.qvector_iter"; pub const Q_HASHTBL_OBJ_S: &str = "struct.qhashtbl_obj_s"; +pub const Q_HASHTBL_ITER: &str = "struct.qhashtbl_iter"; pub const SSZ_ENCODE_LEN: &str = "ssz_encode_len"; pub const IR_BUILTIN_SSZ_ENCODE_VOID_PTR: &str = "ir_builtin_ssz_encode_void_ptr"; pub const IR_BUILTIN_SSZ_DECODE_VOID_PTR: &str = "ir_builtin_ssz_decode_void_ptr"; diff --git a/smart_ir/src/ir_codegen/context.rs b/smart_ir/src/ir_codegen/context.rs index 4a46ca0..a479021 100644 --- a/smart_ir/src/ir_codegen/context.rs +++ b/smart_ir/src/ir_codegen/context.rs @@ -53,7 +53,7 @@ pub type CompileResult<'a> = Result, CodeGenError>; /// The compiler scope. pub struct Scope<'ctx> { pub variables: RefCell>>, - pub closures: RefCell>>, + pub variable_tys: RefCell>>, } #[derive(Default)] @@ -137,7 +137,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { if let Some(ptr) = global_strings.get(value) { *ptr } else { - let gv = unsafe { self.builder.build_global_string(value, name) }; + let gv = unsafe { self.builder.build_global_string(value, name).unwrap() }; let ptr = self .ptr_cast( gv.as_pointer_value().into(), @@ -218,46 +218,51 @@ impl<'ctx> BuilderMethods for IR2LLVMCodeGenContext<'ctx> { /// SSA ret instruction. #[inline] fn ret_void(&self) { - self.builder.build_return(None); + self.builder.build_return(None).unwrap(); } /// SSA ret instruction with returned value. #[inline] fn ret(&self, v: Self::Value) { - self.builder.build_return(Some(&v)); + self.builder.build_return(Some(&v)).unwrap(); } /// SSA br instruction. #[inline] fn br(&self, dest: Self::BasicBlock) { - self.builder.build_unconditional_branch(dest); + self.builder.build_unconditional_branch(dest).unwrap(); } /// SSA cond br instruction. #[inline] fn cond_br(&self, cond: Self::Value, then_bb: Self::BasicBlock, else_bb: Self::BasicBlock) { self.builder - .build_conditional_branch(cond.into_int_value(), then_bb, else_bb); + .build_conditional_branch(cond.into_int_value(), then_bb, else_bb) + .unwrap(); } /// SSA load instruction. #[inline] - fn load(&self, ptr: Self::Value, name: &str) -> Self::Value { - self.builder.build_load(ptr.into_pointer_value(), name) + fn load(&self, pointee_ty: Self::Type, ptr: Self::Value, name: &str) -> Self::Value { + self.builder + .build_load(pointee_ty, ptr.into_pointer_value(), name) + .unwrap() } /// SSA cast int to pointer. #[inline] fn int_to_ptr(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { self.builder .build_int_to_ptr(val.into_int_value(), dest_ty.into_pointer_type(), "") + .unwrap() .into() } /// SSA bit cast. #[inline] fn bit_cast(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { - self.builder.build_bitcast(val, dest_ty, "") + self.builder.build_bitcast(val, dest_ty, "").unwrap() } /// SSA int cast. #[inline] fn int_cast(&self, val: Self::Value, dest_ty: Self::Type, _is_signed: bool) -> Self::Value { self.builder .build_int_cast(val.into_int_value(), dest_ty.into_int_type(), "") + .unwrap() .into() } /// SSA pointer cast. @@ -265,6 +270,7 @@ impl<'ctx> BuilderMethods for IR2LLVMCodeGenContext<'ctx> { fn ptr_cast(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value { self.builder .build_pointer_cast(val.into_pointer_value(), dest_ty.into_pointer_type(), "") + .unwrap() .into() } /// Lookup a known function named `name`. @@ -1116,7 +1122,6 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { mpm.add_loop_unroll_and_jam_pass(); mpm.add_loop_unroll_pass(); - mpm.add_loop_unswitch_pass(); assert!(mpm.run_on(&self.module)); } @@ -1126,9 +1131,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let ty = function.params.get(i).expect(INTERNAL_ERROR_MSG); let name = i.to_string(); let ty = self.llvm_type(ty); - let ptr = self.builder.build_alloca(ty, ""); - self.builder.build_store(ptr, *param); - self.add_variable(&name, ptr); + let ptr = self.builder.build_alloca(ty, "").unwrap(); + self.builder.build_store(ptr, *param).unwrap(); + self.add_variable(&name, ptr, ty); vars_list.insert(name, ty); } } @@ -1210,14 +1215,20 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { "", ); - let ver = self.builder.build_load(ver_ptr, ""); - - let is_valid_ver = self.builder.build_int_compare( - IntPredicate::EQ, - ver.into_int_value(), - self.i8_value(DEFAULT_VERSION as u64).into_int_value(), - "", - ); + let ver = self + .builder + .build_load(self.i8_type(), ver_ptr, "") + .unwrap(); + + let is_valid_ver = self + .builder + .build_int_compare( + IntPredicate::EQ, + ver.into_int_value(), + self.i8_value(DEFAULT_VERSION as u64).into_int_value(), + "", + ) + .unwrap(); let then_block = self.append_block("datastream_decode_arg_value_block"); let else_block = self.append_block("datastream_version_error_block"); @@ -1238,14 +1249,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { &name, ); offset = next_offset; - + let llvm_ty = self.llvm_type(ty); if ty.is_reference_type() || ty.is_string() { let ptr_to_value = - self.builder.build_alloca(self.llvm_type(ty), ""); - self.builder.build_store(ptr_to_value, ptr); - self.add_variable(&name, ptr_to_value); + self.builder.build_alloca(llvm_ty, "").unwrap(); + self.builder.build_store(ptr_to_value, ptr).unwrap(); + self.add_variable(&name, ptr_to_value, llvm_ty); } else { - self.add_variable(&name, ptr); + self.add_variable(&name, ptr, llvm_ty); } } //check the end offset @@ -1266,7 +1277,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { if function.ret.is_void() { self.build_void_call(&internal_function_name, &args); let length = self.i32_value(0); - let data = self.builder.build_alloca(self.i8_type(), ""); + let data = self.builder.build_alloca(self.i8_type(), "").unwrap(); self.build_void_call( HostAPI::SetCallResult.name(), &[data.into(), length], @@ -1527,7 +1538,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { } let scopes = vec![Rc::new(Scope { variables: RefCell::new(IndexMap::default()), - closures: RefCell::new(IndexMap::default()), + variable_tys: RefCell::new(IndexMap::default()), })]; pkg_scopes.insert(String::from(pkgpath), scopes); } @@ -1542,7 +1553,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); let scope = Rc::new(Scope { variables: RefCell::new(IndexMap::default()), - closures: RefCell::new(IndexMap::default()), + variable_tys: RefCell::new(IndexMap::default()), }); scopes.push(scope); } @@ -1561,15 +1572,22 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { } /// Append a variable into the scope - pub fn add_variable(&self, name: &str, pointer: PointerValue<'ctx>) { + pub fn add_variable( + &self, + name: &str, + pointer: PointerValue<'ctx>, + pointee_ty: BasicTypeEnum<'ctx>, + ) { let current_pkgpath = self.current_pkgpath(); let mut pkg_scopes = self.pkg_scopes.borrow_mut(); let msg = format!("pkgpath {current_pkgpath} is not found"); let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); if let Some(last) = scopes.last_mut() { let mut variables = last.variables.borrow_mut(); + let mut variable_tys = last.variable_tys.borrow_mut(); if !variables.contains_key(name) { variables.insert(name.to_string(), pointer); + variable_tys.insert(name.to_string(), pointee_ty); } } } @@ -1596,11 +1614,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { for i in 0..scopes_len { let index = scopes_len - i - 1; let variables_mut = scopes[index].variables.borrow_mut(); + let variable_tys = scopes[index].variable_tys.borrow(); if let Some(ptr) = variables_mut.get(&name.to_string()) { - let value = self.builder.build_load(*ptr, name); - result = Ok(value); - break; + if let Some(ty) = variable_tys.get(&name.to_string()) { + let value = self.builder.build_load(*ty, *ptr, name).unwrap(); + result = Ok(value); + break; + } } } result @@ -1626,11 +1647,34 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { None } + pub fn get_variable_ty(&self, name: &str) -> Option> { + let pkgpath = self.current_pkgpath(); + let pkg_scopes = self.pkg_scopes.borrow_mut(); + // User pkgpath + let scopes = pkg_scopes + .get(&pkgpath) + .unwrap_or_else(|| panic!("package {pkgpath} is not found")); + // Scopes 0 is builtin scope, Scopes 1 is the global scope, Scopes 2~ are the local scopes + let scopes_len = scopes.len(); + for i in 0..scopes_len { + let index = scopes_len - i - 1; + let variable_tys = scopes[index].variable_tys.borrow(); + if let Some(var) = variable_tys.get(&name.to_string()) { + return Some(*var); + } + } + + None + } + pub fn build_or_get_variable(&self, name: &str, var_ty: &Type) -> PointerValue<'ctx> { let ptr = self.get_variable_ptr(name); if ptr.is_none() { - let new_ptr = self.builder.build_alloca(self.llvm_type(var_ty), name); - self.add_variable(name, new_ptr); + let new_ptr = self + .builder + .build_alloca(self.llvm_type(var_ty), name) + .unwrap(); + self.add_variable(name, new_ptr, self.llvm_type(var_ty)); return new_ptr; } @@ -1661,6 +1705,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { mhdrut, "", ) + .unwrap() .into(); self.cond_br(is_truth, then_block, else_block); } @@ -1697,7 +1742,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { pub fn build_void_call(&self, name: &str, args: &[BasicValueEnum]) { let args: Vec = args.iter().map(|v| (*v).into()).collect(); self.builder - .build_call(self.lookup_function(name), &args, ""); + .build_call(self.lookup_function(name), &args, "") + .unwrap(); } /// Build a function call with the return value @@ -1706,6 +1752,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let args: Vec = args.iter().map(|v| (*v).into()).collect(); self.builder .build_call(self.lookup_function(name), &args, "") + .unwrap() .try_as_basic_value() .left() .unwrap_or_else(|| panic!("{FUNCTION_RETURN_VALUE_NOT_FOUND_MSG}: {name}")) @@ -1754,7 +1801,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let error_block = self.append_block("error"); self.builder - .build_conditional_branch(overflow, error_block, success_block); + .build_conditional_branch(overflow, error_block, success_block) + .unwrap(); self.builder.position_at_end(error_block); let msg = format!("math int {op} overflow"); @@ -1765,7 +1813,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i32_value(msg.len() as u64), ], ); - self.builder.build_unreachable(); + self.builder.build_unreachable().unwrap(); self.builder.position_at_end(success_block); @@ -1911,15 +1959,22 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.build_void_call("ir_builtin_print", &[val]); } - pub fn memset_struct_ptr(&self, ptr: PointerValue<'ctx>, val: i8) { - let void_ptr = self.builder.build_bitcast(ptr, self.i8_ptr_type(), ""); + pub fn memset_struct_ptr( + &self, + ptr: PointerValue<'ctx>, + pointee_ty: BasicTypeEnum<'ctx>, + val: i8, + ) { + let void_ptr = self + .builder + .build_bitcast(ptr, self.i8_ptr_type(), "") + .unwrap(); self.build_void_call( "__memset", &[ void_ptr, self.i8_value(val as u64), - ptr.get_type() - .get_element_type() + pointee_ty .size_of() .unwrap() .const_cast(self.i32_type().into_int_type(), false) @@ -1964,13 +2019,18 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { for (i, item) in data_str.iter().enumerate() { let ch = unsafe { - self.builder.build_in_bounds_gep( - arr_value, - &[self.native_i8(i.try_into().unwrap())], - "", - ) + self.builder + .build_in_bounds_gep( + self.i8_type(), + arr_value, + &[self.native_i8(i.try_into().unwrap())], + "", + ) + .unwrap() }; - self.builder.build_store(ch, self.i8_value(*item as u64)); + self.builder + .build_store(ch, self.i8_value(*item as u64)) + .unwrap(); } (arr_value, arr_length) diff --git a/smart_ir/src/ir_codegen/encoding.rs b/smart_ir/src/ir_codegen/encoding.rs index 9baa347..c552b4d 100644 --- a/smart_ir/src/ir_codegen/encoding.rs +++ b/smart_ir/src/ir_codegen/encoding.rs @@ -80,7 +80,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { } else { let value_llvm_ptr_ty = self.ptr_type_to(self.llvm_type(ty)); let value_ptr = self.ptr_cast(void_ptr, value_llvm_ptr_ty); - return self.builder.build_load(value_ptr.into_pointer_value(), ""); + return self + .builder + .build_load(self.llvm_type(ty), value_ptr.into_pointer_value(), "") + .unwrap(); } } @@ -95,8 +98,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let void_ptr = if ty.is_reference_type() || ty.is_string() { self.ptr_cast(value, self.i8_ptr_type()) } else { - let val_ptr = self.builder.build_alloca(self.llvm_type(ty), ""); - self.builder.build_store(val_ptr, value); + let val_ptr = self.builder.build_alloca(self.llvm_type(ty), "").unwrap(); + self.builder.build_store(val_ptr, value).unwrap(); self.ptr_cast(val_ptr.into(), self.i8_ptr_type()) }; @@ -116,6 +119,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i32_value(U16_SIZE).into_int_value(), "", ) + .unwrap() .into(); let versioned_value_ptr = self.build_call(MALLOC_FUNC_NAME, &[versioned_value_length]); @@ -173,9 +177,11 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { name, ) } else if ty.is_boolean() { - self.builder.build_alloca(self.llvm_type(&Type::u8()), name) + self.builder + .build_alloca(self.llvm_type(&Type::u8()), name) + .unwrap() } else if ty.is_integer() { - self.builder.build_alloca(self.llvm_type(ty), name) + self.builder.build_alloca(self.llvm_type(ty), name).unwrap() } else if ty.is_array() { let stream_len = len; // Data stream decoding vector buffer @@ -218,7 +224,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { &[ptr.into(), data, offset, len], ); if ty.is_boolean() { - let u8_value = self.builder.build_load(ptr, ""); + let u8_value = self + .builder + .build_load(self.llvm_type(&Type::u8()), ptr, "") + .unwrap(); let bool_value: BasicValueEnum = self .builder .build_int_compare( @@ -227,9 +236,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i8_value(0).into_int_value(), "", ) + .unwrap() .into(); - ptr = self.builder.build_alloca(self.llvm_type(ty), name); - self.builder.build_store(ptr, bool_value); + ptr = self.builder.build_alloca(self.llvm_type(ty), name).unwrap(); + self.builder.build_store(ptr, bool_value).unwrap(); } (ptr, next_offset) } @@ -247,18 +257,22 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { // Temporary solution for passing parampack parameter if !is_parampack && types.len() == 1 && types[0].is_parampack() { let len = self.vector_len(values[0]); - let total_size = - self.builder - .build_int_add(len, self.i32_value(1).into_int_value(), ""); + let total_size = self + .builder + .build_int_add(len, self.i32_value(1).into_int_value(), "") + .unwrap(); let bytes = self.build_call(MALLOC_FUNC_NAME, &[total_size.into()]); let first_byte = unsafe { - self.builder.build_in_bounds_gep( - bytes.into_pointer_value(), - &[self.native_i8(0)], - "", - ) + self.builder + .build_in_bounds_gep( + self.i8_type(), + bytes.into_pointer_value(), + &[self.native_i8(0)], + "", + ) + .unwrap() }; - self.builder.build_store(first_byte, version); + self.builder.build_store(first_byte, version).unwrap(); self.build_call( "memcpy_offset", @@ -275,9 +289,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let mut total_size = self.data_stream_len(types, values); if !is_parampack { - total_size = - self.builder - .build_int_add(total_size, self.i32_value(1).into_int_value(), ""); + total_size = self + .builder + .build_int_add(total_size, self.i32_value(1).into_int_value(), "") + .unwrap(); } let bytes = self @@ -287,9 +302,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { // Set the first version byte. let first_byte = unsafe { self.builder - .build_in_bounds_gep(bytes, &[self.native_i8(0)], "") - }; - self.builder.build_store(first_byte, version); + .build_in_bounds_gep(self.i8_type(), bytes, &[self.native_i8(0)], "") + } + .unwrap(); + self.builder.build_store(first_byte, version).unwrap(); } let mut offset = if is_parampack { @@ -336,7 +352,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let leb128_bytes_length = self .build_call(ULEB128_VALUE_LENGTH_FUNC_NAME, &[len.into()]) .into_int_value(); - self.builder.build_int_add(len, leb128_bytes_length, "") + self.builder + .build_int_add(len, leb128_bytes_length, "") + .unwrap() } else if ty.is_array() { let len = self.q_vector_len(*value); let elem_size = if let Type::Array { elem, len: _ } = ty { @@ -350,18 +368,23 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let leb128_bytes_length = self .build_call(ULEB128_VALUE_LENGTH_FUNC_NAME, &[len.into()]) .into_int_value(); - self.builder.build_int_add( - self.builder.build_int_mul(len, elem_size, ""), - leb128_bytes_length, - "", - ) + self.builder + .build_int_add( + self.builder.build_int_mul(len, elem_size, "").unwrap(), + leb128_bytes_length, + "", + ) + .unwrap() } else if ty.is_map() { self.build_call("qhashtbl_total_space", &[*value]) .into_int_value() } else { unimplemented!() }; - total_size = self.builder.build_int_add(total_size, val_size, "") + total_size = self + .builder + .build_int_add(total_size, val_size, "") + .unwrap() } total_size } @@ -376,11 +399,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ) -> PointerValue<'ctx> { // Data stream decoding vector buffer let size = self.build_call(DECODE_ULEB128_VALUE_FUNC_NAME, &[data, offset, len]); - let init = self.builder.build_int_to_ptr( - self.llvm_context.i128_type().const_zero(), - self.i8_ptr_type().into_pointer_type(), - name, - ); + let init = self + .builder + .build_int_to_ptr( + self.llvm_context.i128_type().const_zero(), + self.i8_ptr_type().into_pointer_type(), + name, + ) + .unwrap(); self.build_call(VECTOR_NEW_FUNC_NAME, &[size, elem_size, init.into()]) .into_pointer_value() } diff --git a/smart_ir/src/ir_codegen/intrinsic/builtin.rs b/smart_ir/src/ir_codegen/intrinsic/builtin.rs index 7d31d03..9738bfe 100644 --- a/smart_ir/src/ir_codegen/intrinsic/builtin.rs +++ b/smart_ir/src/ir_codegen/intrinsic/builtin.rs @@ -88,8 +88,11 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let void_ptr = if val_ty.is_reference_type() || val_ty.is_string() { self.ptr_cast(val, self.i8_ptr_type()) } else { - let val_ptr = self.builder.build_alloca(self.llvm_type(val_ty), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self + .builder + .build_alloca(self.llvm_type(val_ty), "") + .unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); self.ptr_cast(val_ptr.into(), self.i8_ptr_type()) }; self.build_call("ir_builtin_rlp_encode", &[offset_value, void_ptr]) @@ -108,8 +111,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { if ret.is_reference_type() || ret.is_string() { self.ptr_cast(void_ptr, self.llvm_type(ret)) } else { - let val_ptr = self.ptr_cast(void_ptr, self.ptr_type_to(self.llvm_type(ret))); - self.builder.build_load(val_ptr.into_pointer_value(), "") + self.builder + .build_load(self.llvm_type(ret), void_ptr.into_pointer_value(), "") + .unwrap() } } @@ -129,8 +133,11 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let void_ptr = if val_ty.is_reference_type() || val_ty.is_string() { self.ptr_cast(val, self.i8_ptr_type()) } else { - let val_ptr = self.builder.build_alloca(self.llvm_type(val_ty), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self + .builder + .build_alloca(self.llvm_type(val_ty), "") + .unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); self.ptr_cast(val_ptr.into(), self.i8_ptr_type()) }; self.build_call("ir_builtin_json_encode", &[offset_value, void_ptr]) @@ -149,8 +156,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { if ret.is_reference_type() || ret.is_string() { self.ptr_cast(void_ptr, self.llvm_type(ret)) } else { - let val_ptr = self.ptr_cast(void_ptr, self.ptr_type_to(self.llvm_type(ret))); - self.builder.build_load(val_ptr.into_pointer_value(), "") + self.builder + .build_load(self.llvm_type(ret), void_ptr.into_pointer_value(), "") + .unwrap() } } @@ -170,8 +178,11 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let void_ptr = if val_ty.is_reference_type() || val_ty.is_string() { self.ptr_cast(val, self.i8_ptr_type()) } else { - let val_ptr = self.builder.build_alloca(self.llvm_type(val_ty), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self + .builder + .build_alloca(self.llvm_type(val_ty), "") + .unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); self.ptr_cast(val_ptr.into(), self.i8_ptr_type()) }; self.build_call("ir_builtin_ssz_encode", &[offset_value, void_ptr]) @@ -191,7 +202,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.ptr_cast(void_ptr, self.llvm_type(ret)) } else { let val_ptr = self.ptr_cast(void_ptr, self.ptr_type_to(self.llvm_type(ret))); - self.builder.build_load(val_ptr.into_pointer_value(), "") + self.builder + .build_load(self.llvm_type(ret), val_ptr.into_pointer_value(), "") + .unwrap() } } @@ -211,7 +224,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { if ret.is_reference_type() || ret.is_string() { void_ptr.into() } else { - self.builder.build_load(void_ptr, "") + self.builder + .build_load(self.llvm_type(ret), void_ptr, "") + .unwrap() } } @@ -245,20 +260,15 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let length = self .build_call(HostAPI::GetCallResultLength.name(), &[]) .into_int_value(); - let data = self - .build_call(MALLOC_FUNC_NAME, &[length.into()]) - .into_pointer_value(); - let data = unsafe { - self.builder - .build_in_bounds_gep(data, &[self.native_i8(0)], "") - .into() - }; + let data = self.build_call(MALLOC_FUNC_NAME, &[length.into()]); self.build_void_call(HostAPI::GetCallResult.name(), &[data]); let (ptr, _) = self.data_stream_decode(ret, data, self.i32_value(1), length.into(), ""); if ret.is_reference_type() || ret.is_string() { ptr.into() } else { - self.builder.build_load(ptr, "") + self.builder + .build_load(self.llvm_type(ret), ptr, "") + .unwrap() } } else { self.i32_value(1) @@ -272,14 +282,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { _ret: &Type, ) -> BasicValueEnum<'ctx> { let length = self.build_call(HostAPI::GetCallResultLength.name(), &[]); - let data = self - .build_call(MALLOC_FUNC_NAME, &[length]) - .into_pointer_value(); - let data = unsafe { - self.builder - .build_in_bounds_gep(data, &[self.native_i8(0)], "") - .into() - }; + let data = self.build_call(MALLOC_FUNC_NAME, &[length]); self.build_void_call(HostAPI::GetCallResult.name(), &[data]); diff --git a/smart_ir/src/ir_codegen/intrinsic/map.rs b/smart_ir/src/ir_codegen/intrinsic/map.rs index b2380d7..5734918 100644 --- a/smart_ir/src/ir_codegen/intrinsic/map.rs +++ b/smart_ir/src/ir_codegen/intrinsic/map.rs @@ -5,7 +5,9 @@ use inkwell::{types::BasicType, values::BasicValueEnum}; use crate::ir::cfg::Type; +use crate::ir_codegen::builtin_constants::Q_HASHTBL_ITER; use crate::ir_codegen::traits::{BaseTypeMethods, BuilderMethods}; +use crate::ir_codegen::ty::Q_MAP_LLVM_TY; use crate::ir_codegen::{ builtin_constants::{Q_HASHTBL_OBJ_S, VECTOR_NEW_FUNC_NAME}, context::IR2LLVMCodeGenContext, @@ -28,22 +30,24 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let key32: BasicValueEnum = self .builder .build_ptr_to_int(self.vector_bytes(key), self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key32, self.i64_type(), false) } else if key_ty.is_integer() { self.int_cast(key, self.i64_type(), false) } else { - let ptr = self.builder.build_alloca(key.get_type(), ""); - self.builder.build_store(ptr, key); + let ptr = self.builder.build_alloca(key.get_type(), "").unwrap(); + self.builder.build_store(ptr, key).unwrap(); let key32: BasicValueEnum = self .builder .build_ptr_to_int(ptr, self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key32, self.i64_type(), false) }; - let val_ptr = self.builder.build_alloca(val.get_type(), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self.builder.build_alloca(val.get_type(), "").unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); let entry_u8_ptr_value = self.ptr_cast(val_ptr.into(), self.i8_ptr_type()); @@ -75,16 +79,18 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(self.vector_bytes(key), self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) } else if key_ty.is_integer() { self.int_cast(key, self.i64_type(), false) } else { - let ptr = self.builder.build_alloca(key.get_type(), ""); - self.builder.build_store(ptr, key); + let ptr = self.builder.build_alloca(key.get_type(), "").unwrap(); + self.builder.build_store(ptr, key).unwrap(); let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(ptr, self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) }; @@ -97,10 +103,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { false, ); - let value_llvm_ptr_ty = self.ptr_type_to(self.llvm_type(ret)); - // the part of qhashtbl_get accepts value is a pointer points to actual value(i8*) - let value_ptr = self.ptr_cast(data.into(), value_llvm_ptr_ty); - self.builder.build_load(value_ptr.into_pointer_value(), "") + self.builder + .build_load(self.ptr_type_to(self.llvm_type(ret)), data, "") + .unwrap() } pub fn build_map_contains_key( @@ -117,16 +122,18 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(self.vector_bytes(key), self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) } else if key_ty.is_integer() { self.int_cast(key, self.i64_type(), false) } else { - let ptr = self.builder.build_alloca(key.get_type(), ""); - self.builder.build_store(ptr, key); + let ptr = self.builder.build_alloca(key.get_type(), "").unwrap(); + self.builder.build_store(ptr, key).unwrap(); let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(ptr, self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) }; @@ -148,16 +155,18 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(self.vector_bytes(key), self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) } else if key_ty.is_integer() { self.int_cast(key, self.i64_type(), false) } else { - let ptr = self.builder.build_alloca(key.get_type(), ""); - self.builder.build_store(ptr, key); + let ptr = self.builder.build_alloca(key.get_type(), "").unwrap(); + self.builder.build_store(ptr, key).unwrap(); let key_i32: BasicValueEnum = self .builder .build_ptr_to_int(ptr, self.i32_type().into_int_type(), "") + .unwrap() .into(); self.int_cast(key_i32, self.i64_type(), false) }; @@ -174,9 +183,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let map_ptr = *params.get(0).unwrap(); let iter_size = self - .llvm_type(&Type::map_iter()) - .into_pointer_type() - .get_element_type() + .llvm_context + .get_struct_type(Q_HASHTBL_ITER) + .unwrap() .size_of() .unwrap() .const_cast(self.i32_type().into_int_type(), false); @@ -186,10 +195,15 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let map_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 0, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 0, + "", + ) .unwrap(); - self.builder.build_store(map_field, map_ptr); + self.builder.build_store(map_field, map_ptr).unwrap(); let qhashtbl_obj_ty = self.module.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(); let malloc_ptr = self.build_call( @@ -202,14 +216,19 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ); let obj_ptr = self.ptr_cast(malloc_ptr, self.ptr_type_to(qhashtbl_obj_ty.into())); - self.memset_struct_ptr(obj_ptr.into_pointer_value(), 0); + self.memset_struct_ptr(obj_ptr.into_pointer_value(), qhashtbl_obj_ty.into(), 0); let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - self.builder.build_store(obj_field, obj_ptr); + self.builder.build_store(obj_field, obj_ptr).unwrap(); iter_ptr } @@ -224,16 +243,40 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let map_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 0, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 0, + "", + ) + .unwrap(); + let map_ptr = self + .builder + .build_load( + self.llvm_context.get_struct_type(Q_MAP_LLVM_TY).unwrap(), + map_field, + "", + ) .unwrap(); - let map_ptr = self.builder.build_load(map_field, ""); let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.llvm_context.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); self.build_hashtbl_getnext( map_ptr.into_pointer_value(), @@ -252,17 +295,37 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.llvm_context.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); let key_field = self .builder - .build_struct_gep(obj_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(), + obj_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let key_data = self.builder.build_load(key_field, ""); + let key_data = self + .builder + .build_load(self.i64_type(), key_field, "") + .unwrap(); if ret.is_string() { let key_bytes = self.int_to_ptr(key_data, self.i8_ptr_type()); @@ -278,6 +341,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.llvm_type(ret).into_int_type(), "", ) + .unwrap() .into() } } @@ -292,18 +356,43 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.llvm_context.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); let value_field = self .builder - .build_struct_gep(obj_ptr.into_pointer_value(), 2, "") + .build_struct_gep( + self.llvm_context.get_struct_type(Q_HASHTBL_OBJ_S).unwrap(), + obj_ptr.into_pointer_value(), + 2, + "", + ) .unwrap(); - let value_byte = self.builder.build_load(value_field, ""); - let value_ptr = self.ptr_cast(value_byte, self.ptr_type_to(self.llvm_type(ret))); - self.builder.build_load(value_ptr.into_pointer_value(), "") + let value_byte = self + .builder + .build_load(self.i8_ptr_type(), value_field, "") + .unwrap(); + self.builder + .build_load( + self.ptr_type_to(self.llvm_type(ret)), + value_byte.into_pointer_value(), + "", + ) + .unwrap() } } diff --git a/smart_ir/src/ir_codegen/intrinsic/mod.rs b/smart_ir/src/ir_codegen/intrinsic/mod.rs index 23644b0..3cf7099 100644 --- a/smart_ir/src/ir_codegen/intrinsic/mod.rs +++ b/smart_ir/src/ir_codegen/intrinsic/mod.rs @@ -101,9 +101,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let ret_val = intrinsic_builder(self, func.get_params().as_slice(), params, ret); if ret.is_void() { - self.builder.build_return(None); + self.builder.build_return(None).unwrap(); } else { - self.builder.build_return(Some(&ret_val)); + self.builder.build_return(Some(&ret_val)).unwrap(); } if let Some(pre_bb) = pre_bb { diff --git a/smart_ir/src/ir_codegen/intrinsic/storage.rs b/smart_ir/src/ir_codegen/intrinsic/storage.rs index 59779b6..8e439a9 100644 --- a/smart_ir/src/ir_codegen/intrinsic/storage.rs +++ b/smart_ir/src/ir_codegen/intrinsic/storage.rs @@ -24,11 +24,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let elem_ty = params_ty.get(1).unwrap(); let (value_ptr, value_length) = self.ssz_encode_with_version(elem_ty, None, val); - let storage_path_ptr = self.builder.build_int_to_ptr( - storage_path.into_int_value(), - self.storage_path_ptr_type().into_pointer_type(), - "", - ); + let storage_path_ptr = self + .builder + .build_int_to_ptr( + storage_path.into_int_value(), + self.storage_path_ptr_type().into_pointer_type(), + "", + ) + .unwrap(); let size_path_ptr = self.build_call( "storage_path_join_must_immut_string", @@ -39,11 +42,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ], ); - let size_path = self.builder.build_ptr_to_int( - size_path_ptr.into_pointer_value(), - self.i32_type().into_int_type(), - "", - ); + let size_path = self + .builder + .build_ptr_to_int( + size_path_ptr.into_pointer_value(), + self.i32_type().into_int_type(), + "", + ) + .unwrap(); self.build_void_call( "builtin_storage_array_push", @@ -59,11 +65,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { _ret: &Type, ) -> BasicValueEnum<'ctx> { let storage_path = *params.get(0).unwrap(); - let storage_path_ptr = self.builder.build_int_to_ptr( - storage_path.into_int_value(), - self.storage_path_ptr_type().into_pointer_type(), - "", - ); + let storage_path_ptr = self + .builder + .build_int_to_ptr( + storage_path.into_int_value(), + self.storage_path_ptr_type().into_pointer_type(), + "", + ) + .unwrap(); let size_path_ptr = self.build_call( "storage_path_join_must_immut_string", &[ @@ -72,11 +81,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i32_value(4), ], ); - let size_path = self.builder.build_ptr_to_int( - size_path_ptr.into_pointer_value(), - self.i32_type().into_int_type(), - "", - ); + let size_path = self + .builder + .build_ptr_to_int( + size_path_ptr.into_pointer_value(), + self.i32_type().into_int_type(), + "", + ) + .unwrap(); self.build_void_call( "builtin_storage_array_pop", @@ -92,11 +104,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { _ret: &Type, ) -> BasicValueEnum<'ctx> { let storage_path = *params.get(0).unwrap(); - let storage_path_ptr = self.builder.build_int_to_ptr( - storage_path.into_int_value(), - self.storage_path_ptr_type().into_pointer_type(), - "", - ); + let storage_path_ptr = self + .builder + .build_int_to_ptr( + storage_path.into_int_value(), + self.storage_path_ptr_type().into_pointer_type(), + "", + ) + .unwrap(); let size_path_ptr = self.build_call( "storage_path_join_must_immut_string", &[ @@ -167,6 +182,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i32_value(DATA_EMPTY_LENGTH as u64).into_int_value(), "", ) + .unwrap() .into() } @@ -217,11 +233,14 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ) -> BasicValueEnum<'ctx> { let storage_path = *params.get(0).unwrap(); let index = *params.get(1).unwrap(); - let storage_path_ptr = self.builder.build_int_to_ptr( - storage_path.into_int_value(), - self.storage_path_ptr_type().into_pointer_type(), - "", - ); + let storage_path_ptr = self + .builder + .build_int_to_ptr( + storage_path.into_int_value(), + self.storage_path_ptr_type().into_pointer_type(), + "", + ) + .unwrap(); let size_path_ptr = self.build_call( "storage_path_join_must_immut_string", @@ -255,6 +274,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.i32_value(DATA_EMPTY_LENGTH as u64).into_int_value(), "", ) + .unwrap() .into() } diff --git a/smart_ir/src/ir_codegen/intrinsic/vector.rs b/smart_ir/src/ir_codegen/intrinsic/vector.rs index f6df7c8..bba9548 100644 --- a/smart_ir/src/ir_codegen/intrinsic/vector.rs +++ b/smart_ir/src/ir_codegen/intrinsic/vector.rs @@ -7,11 +7,12 @@ use inkwell::values::BasicValueEnum; use crate::ir::cfg::Type; use crate::ir_codegen::builtin_constants::{ - Q_VECTOR_OBJ_S, Q_VEC_NEW_FUNC_NAME, Q_VEC_SLICE_FUNC_NAME, + Q_VECTOR_ITER, Q_VECTOR_OBJ_S, Q_VEC_NEW_FUNC_NAME, Q_VEC_SLICE_FUNC_NAME, }; use crate::ir_codegen::context::IR2LLVMCodeGenContext; use crate::ir_codegen::encoding::MALLOC_FUNC_NAME; use crate::ir_codegen::traits::{BaseTypeMethods, BuilderMethods}; +use crate::ir_codegen::ty::Q_VEC_LLVM_TY; impl<'ctx> IR2LLVMCodeGenContext<'ctx> { pub fn build_vector_set( @@ -27,8 +28,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let idx = self.int_cast(idx, self.i32_type(), true); - let val_ptr = self.builder.build_alloca(val.get_type(), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self.builder.build_alloca(val.get_type(), "").unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); // the part of qvector_setat accepts value is a pointer points to actual value(i8*) let store_value_u8_ptr = self.ptr_cast(val_ptr.into(), self.i8_ptr_type()); @@ -63,7 +64,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { // need convert i8* to the pointer of target type of vector element, struct T** or int32* etc. that is pointer to pointer or primitive type pointer let value_ptr = self.ptr_cast(pointer_to_element, value_llvm_ptr_ty); - self.builder.build_load(value_ptr.into_pointer_value(), "") + self.builder + .build_load(self.llvm_type(ret), value_ptr.into_pointer_value(), "") + .unwrap() } pub fn build_vector_push( @@ -75,8 +78,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let vec_ptr = *params.get(0).unwrap(); let val = *params.get(1).unwrap(); - let val_ptr = self.builder.build_alloca(val.get_type(), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self.builder.build_alloca(val.get_type(), "").unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); // the part of qvector_setat accepts value is a pointer points to actual value(i8*) let store_value_u8_ptr = self.ptr_cast(val_ptr.into(), self.i8_ptr_type()); @@ -94,9 +97,9 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let vec_ptr = *params.get(0).unwrap(); let iter_size = self - .llvm_type(&Type::vec_iter()) - .into_pointer_type() - .get_element_type() + .module + .get_struct_type(Q_VECTOR_ITER) + .unwrap() .size_of() .unwrap() .const_cast(self.i32_type().into_int_type(), false); @@ -106,10 +109,15 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let vec_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 0, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 0, + "", + ) .unwrap(); - self.builder.build_store(vec_field, vec_ptr); + self.builder.build_store(vec_field, vec_ptr).unwrap(); let qvector_obj_ty = self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(); let malloc_ptr = self.build_call( @@ -122,14 +130,19 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ); let obj_ptr = self.ptr_cast(malloc_ptr, self.ptr_type_to(qvector_obj_ty.into())); - self.memset_struct_ptr(obj_ptr.into_pointer_value(), 0); + self.memset_struct_ptr(obj_ptr.into_pointer_value(), qvector_obj_ty.into(), 0); let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - self.builder.build_store(obj_field, obj_ptr); + self.builder.build_store(obj_field, obj_ptr).unwrap(); iter_ptr } @@ -144,16 +157,40 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let vec_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 0, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 0, + "", + ) + .unwrap(); + let vec_ptr = self + .builder + .build_load( + self.module.get_struct_type(Q_VEC_LLVM_TY).unwrap(), + vec_field, + "", + ) .unwrap(); - let vec_ptr = self.builder.build_load(vec_field, ""); let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); self.build_call( "qvector_getnext", @@ -171,23 +208,44 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); let idx_field = self .builder - .build_struct_gep(obj_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(), + obj_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let next_idx = self.builder.build_load(idx_field, ""); + let next_idx = self + .builder + .build_load(self.i32_type(), idx_field, "") + .unwrap(); self.builder .build_int_nsw_sub( next_idx.into_int_value(), self.i32_value(1).into_int_value(), "", ) + .unwrap() .into() } @@ -200,17 +258,39 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let iter_ptr = *params.get(0).unwrap(); let obj_field = self .builder - .build_struct_gep(iter_ptr.into_pointer_value(), 1, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_ITER).unwrap(), + iter_ptr.into_pointer_value(), + 1, + "", + ) .unwrap(); - let obj_ptr = self.builder.build_load(obj_field, ""); + let obj_ptr = self + .builder + .build_load( + self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(), + obj_field, + "", + ) + .unwrap(); let data_field = self .builder - .build_struct_gep(obj_ptr.into_pointer_value(), 0, "") + .build_struct_gep( + self.module.get_struct_type(Q_VECTOR_OBJ_S).unwrap(), + obj_ptr.into_pointer_value(), + 0, + "", + ) + .unwrap(); + let data_ptr = self + .builder + .build_load(self.i8_ptr_type(), data_field, "") .unwrap(); - let data_ptr = self.builder.build_load(data_field, ""); let elem_ptr = self.ptr_cast(data_ptr, self.ptr_type_to(self.llvm_type(ret))); - self.builder.build_load(elem_ptr.into_pointer_value(), "") + self.builder + .build_load(self.llvm_type(ret), elem_ptr.into_pointer_value(), "") + .unwrap() } pub fn build_vector_insert( @@ -225,8 +305,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let idx = self.int_cast(idx, self.i32_type(), true); - let val_ptr = self.builder.build_alloca(val.get_type(), ""); - self.builder.build_store(val_ptr, val); + let val_ptr = self.builder.build_alloca(val.get_type(), "").unwrap(); + self.builder.build_store(val_ptr, val).unwrap(); // the part of qvector_setat accepts value is a pointer points to actual value(i8*) let store_value_u8_ptr = self.ptr_cast(val_ptr.into(), self.i8_ptr_type()); diff --git a/smart_ir/src/ir_codegen/ir.rs b/smart_ir/src/ir_codegen/ir.rs index 9a0dfb1..33c48c3 100644 --- a/smart_ir/src/ir_codegen/ir.rs +++ b/smart_ir/src/ir_codegen/ir.rs @@ -21,7 +21,7 @@ use crate::ir_codegen::traits::BuilderMethods; use super::{ builtin_constants::{MEMCMP_FUNC, Q_MAP_NEW_FUNC_NAME, VECTOR_NEW_FUNC_NAME}, - context::{CompileResult, IR2LLVMCodeGenContext}, + context::{CodeGenError, CompileResult, IR2LLVMCodeGenContext}, error::FUNCTION_RETURN_VALUE_NOT_FOUND_MSG, }; @@ -50,7 +50,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { }; let ptr = self.build_or_get_variable(&name, &var_ty); - self.builder.build_store(ptr, init_val); + self.builder.build_store(ptr, init_val).unwrap(); self.ok_result() } InstrDescription::Assignment { id, val } => { @@ -61,7 +61,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { .get_variable_ptr(&name) .unwrap_or_else(|| panic!("can't find variable %{name}")); - self.builder.build_store(ptr, val); + self.builder.build_store(ptr, val).unwrap(); self.ok_result() } @@ -100,12 +100,12 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { } => unimplemented!(), InstrDescription::Not { op } => { let op = self.walk_ir_expr(op)?; - let res = self.builder.build_not(op.into_int_value(), ""); + let res = self.builder.build_not(op.into_int_value(), "").unwrap(); Ok(res.into()) } InstrDescription::BitNot { op } => { let op = self.walk_ir_expr(op)?; - let res = self.builder.build_not(op.into_int_value(), ""); + let res = self.builder.build_not(op.into_int_value(), "").unwrap(); Ok(res.into()) } InstrDescription::Binary { op_code, op1, op2 } => { @@ -131,124 +131,132 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let res: BasicValueEnum = match op_code { BinaryOp::Add => { if expr_ty.is_signed_int() { - self.builder.build_int_nsw_add( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_nsw_add( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } else { - self.builder.build_int_add( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_add(left.into_int_value(), right.into_int_value(), "") + .unwrap() } } BinaryOp::Sub => { if expr_ty.is_signed_int() { - self.builder.build_int_nsw_sub( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_nsw_sub( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } else { - self.builder.build_int_sub( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_sub(left.into_int_value(), right.into_int_value(), "") + .unwrap() } } BinaryOp::Mul => { if expr_ty.is_signed_int() { - self.builder.build_int_nsw_mul( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_nsw_mul( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } else { - self.builder.build_int_mul( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_mul(left.into_int_value(), right.into_int_value(), "") + .unwrap() } } BinaryOp::Div => { if expr_ty.is_signed_int() { - self.builder.build_int_signed_div( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_signed_div( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } else { - self.builder.build_int_unsigned_div( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_unsigned_div( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } } BinaryOp::Mod => { if expr_ty.is_signed_int() { - self.builder.build_int_signed_rem( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_signed_rem( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } else { - self.builder.build_int_unsigned_rem( - left.into_int_value(), - right.into_int_value(), - "", - ) + self.builder + .build_int_unsigned_rem( + left.into_int_value(), + right.into_int_value(), + "", + ) + .unwrap() } } BinaryOp::Exp => self .build_pow(left.into_int_value(), right.into_int_value(), &expr_ty) .into_int_value(), - BinaryOp::And => { - self.builder - .build_and(left.into_int_value(), right.into_int_value(), "") - } + BinaryOp::And => self + .builder + .build_and(left.into_int_value(), right.into_int_value(), "") + .unwrap(), - BinaryOp::BitAnd => { - self.builder - .build_and(left.into_int_value(), right.into_int_value(), "") - } + BinaryOp::BitAnd => self + .builder + .build_and(left.into_int_value(), right.into_int_value(), "") + .unwrap(), - BinaryOp::Or => { - self.builder - .build_or(left.into_int_value(), right.into_int_value(), "") - } + BinaryOp::Or => self + .builder + .build_or(left.into_int_value(), right.into_int_value(), "") + .unwrap(), - BinaryOp::BitOr => { - self.builder - .build_or(left.into_int_value(), right.into_int_value(), "") - } + BinaryOp::BitOr => self + .builder + .build_or(left.into_int_value(), right.into_int_value(), "") + .unwrap(), - BinaryOp::BitXor => { - self.builder - .build_xor(left.into_int_value(), right.into_int_value(), "") - } + BinaryOp::BitXor => self + .builder + .build_xor(left.into_int_value(), right.into_int_value(), "") + .unwrap(), - BinaryOp::Shl => self.builder.build_left_shift( - left.into_int_value(), - right.into_int_value(), - "", - ), - BinaryOp::Shr => self.builder.build_right_shift( - left.into_int_value(), - right.into_int_value(), - expr_ty.is_signed_int(), - "", - ), - BinaryOp::Sar => self.builder.build_right_shift( - left.into_int_value(), - right.into_int_value(), - true, - "", - ), + BinaryOp::Shl => self + .builder + .build_left_shift(left.into_int_value(), right.into_int_value(), "") + .unwrap(), + BinaryOp::Shr => self + .builder + .build_right_shift( + left.into_int_value(), + right.into_int_value(), + expr_ty.is_signed_int(), + "", + ) + .unwrap(), + BinaryOp::Sar => self + .builder + .build_right_shift(left.into_int_value(), right.into_int_value(), true, "") + .unwrap(), } .into(); Ok(res) @@ -304,6 +312,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { right.into_int_value(), "", ) + .unwrap() .into() } else if expr_ty.is_string() { let left_bytes = self.vector_bytes(left); @@ -338,6 +347,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { i1_type.const_all_ones(), "", ) + .unwrap() .into() } _ => unreachable!(), @@ -379,21 +389,57 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { InstrDescription::GetField { ptr, field_path, - field_ty: _, + field_ty, } => { + let ptr_ty = self + .ir_context + .ir_expr_ty(self.current_function.borrow().as_ref().unwrap(), ptr); let mut ptr = self.walk_ir_expr(ptr)?; - for (i, field_idx) in field_path.iter().enumerate() { - let field_ptr = self - .builder - .build_struct_gep(ptr.into_pointer_value(), *field_idx, "") - .unwrap(); - if i + 1 < field_path.len() { - ptr = self.builder.build_load(field_ptr, ""); - } else { - ptr = field_ptr.into(); + if let Some(Type::Pointer(pointee_ty)) = ptr_ty { + let mut struct_ty = pointee_ty; + for (i, field_idx) in field_path.iter().enumerate() { + if let Type::Def(def_ty) = struct_ty.as_ref() { + let field_ptr = self + .builder + .build_struct_gep( + self.llvm_type(&def_ty.ty), + ptr.into_pointer_value(), + *field_idx, + "", + ) + .unwrap(); + if i + 1 < field_path.len() { + if let Type::Compound(fields) = def_ty.ty.as_ref() { + struct_ty = fields.get(*field_idx as usize).unwrap().ty.clone(); + ptr = self + .builder + .build_load(self.llvm_type(&struct_ty), field_ptr, "") + .unwrap(); + } else { + return Err(CodeGenError { + message: "wrong type defination".to_string(), + }); + } + } else { + ptr = field_ptr.into(); + } + } else { + return Err(CodeGenError { + message: + "try to get field from a pointer whose elemet isn't a struct" + .to_string(), + }); + } } - } - let res = self.builder.build_load(ptr.into_pointer_value(), ""); + } else { + return Err(CodeGenError { + message: "try to get field from value which isn't a pointer".to_string(), + }); + }; + let res = self + .builder + .build_load(self.llvm_type(field_ty), ptr.into_pointer_value(), "") + .unwrap(); Ok(res) } InstrDescription::SetField { @@ -401,21 +447,58 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { val, field_path, } => { + let ptr_ty = self + .ir_context + .ir_expr_ty(self.current_function.borrow().as_ref().unwrap(), ptr); let mut ptr = self.walk_ir_expr(ptr)?; let val = self.walk_ir_expr(val)?; - for (i, field_idx) in field_path.iter().enumerate() { - let field_ptr = self - .builder - .build_struct_gep(ptr.into_pointer_value(), *field_idx, "") - .unwrap(); - if i + 1 < field_path.len() { - ptr = self.builder.build_load(field_ptr, ""); - } else { - ptr = field_ptr.into(); + + if let Some(Type::Pointer(pointee_ty)) = ptr_ty { + let mut struct_ty = pointee_ty; + for (i, field_idx) in field_path.iter().enumerate() { + if let Type::Def(def_ty) = struct_ty.as_ref() { + let field_ptr = self + .builder + .build_struct_gep( + self.llvm_type(&struct_ty), + ptr.into_pointer_value(), + *field_idx, + "", + ) + .unwrap(); + if i + 1 < field_path.len() { + if let Type::Compound(fields) = def_ty.ty.as_ref() { + struct_ty = fields.get(*field_idx as usize).unwrap().ty.clone(); + ptr = self + .builder + .build_load(self.llvm_type(&struct_ty), field_ptr, "") + .unwrap(); + } else { + return Err(CodeGenError { + message: "wrong type defination".to_string(), + }); + } + } else { + ptr = field_ptr.into(); + } + } else { + return Err(CodeGenError { + message: + "try to get field from a pointer whose elemet isn't a struct" + .to_string(), + }); + } } + + self.builder + .build_store(ptr.into_pointer_value(), val) + .unwrap(); + self.ok_result() + } else { + Err(CodeGenError { + message: "try to set field to value which isn't a pointer".to_string(), + }) } - self.builder.build_store(ptr.into_pointer_value(), val); - self.ok_result() } InstrDescription::GetStoragePath { storage_path } => { let md = StoragePathExtraArgs::get_from_context(self.ir_context, instr).unwrap(); @@ -506,12 +589,13 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { ret_ty, ); if ret_ty.is_void() { - self.builder.build_call(func, args.as_slice(), ""); + self.builder.build_call(func, args.as_slice(), "").unwrap(); self.ok_result() } else { let ret_val = self .builder .build_call(func, args.as_slice(), "") + .unwrap() .try_as_basic_value() .left() .unwrap_or_else(|| { @@ -541,6 +625,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { self.llvm_type(target_ty).into_int_type(), "", ) + .unwrap() .into(); Ok(ret) } @@ -554,8 +639,11 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let ptr = self .get_variable_ptr(&name) .unwrap_or_else(|| panic!("can't find variable %{name}")); + let ty = self + .get_variable_ty(&name) + .unwrap_or_else(|| panic!("can't find variable %{name}")); - let res = self.builder.build_load(ptr, ""); + let res = self.builder.build_load(ty, ptr, "").unwrap(); Ok(res) } Expr::Instr(instr) => self.walk_instr(instr), @@ -582,11 +670,13 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { IntLiteral::I32(val) => val.to_string(), IntLiteral::I64(val) => val.to_string(), IntLiteral::I128(val) => val.to_string(), + IntLiteral::I256(val) => val.to_string(), IntLiteral::U8(val) => val.to_string(), IntLiteral::U16(val) => val.to_string(), IntLiteral::U32(val) => val.to_string(), IntLiteral::U64(val) => val.to_string(), IntLiteral::U128(val) => val.to_string(), + IntLiteral::U256(val) => val.to_string(), }; self.llvm_type(&lit_ty) diff --git a/smart_ir/src/ir_codegen/storage_path.rs b/smart_ir/src/ir_codegen/storage_path.rs index 2d6acf5..a5a376f 100644 --- a/smart_ir/src/ir_codegen/storage_path.rs +++ b/smart_ir/src/ir_codegen/storage_path.rs @@ -63,9 +63,10 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let leb128_bytes_length = self .build_call("uleb128_value_length", &[val]) .into_int_value(); - let bytes = - self.builder - .build_array_alloca(self.i8_type(), leb128_bytes_length, ""); + let bytes = self + .builder + .build_array_alloca(self.i8_type(), leb128_bytes_length, "") + .unwrap(); self.build_call("encode_uleb128", &[val, bytes.into(), self.i32_value(0)]); (bytes, leb128_bytes_length.into()) @@ -163,59 +164,79 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let key_len = path.keys.len(); let key_count = self.i32_value(key_len.try_into().unwrap()); - let key_datas = self.builder.build_array_alloca( - self.i8_ptr_type(), - self.native_i8(key_len.try_into().unwrap()), - "", - ); - - let key_lengths = self.builder.build_array_alloca( - self.i32_type(), - self.native_i8(key_len.try_into().unwrap()), - "", - ); + let key_datas = self + .builder + .build_array_alloca( + self.i8_ptr_type(), + self.native_i8(key_len.try_into().unwrap()), + "", + ) + .unwrap(); + + let key_lengths = self + .builder + .build_array_alloca( + self.i32_type(), + self.native_i8(key_len.try_into().unwrap()), + "", + ) + .unwrap(); for i in 0..key_len { let key = path.keys.get(i).unwrap(); let (key_data_value, key_data_len) = { self.eval_path_expr(key) }; let key_data = unsafe { - self.builder.build_in_bounds_gep( - key_datas, - &[self.native_i8(i.try_into().unwrap())], - "", - ) + self.builder + .build_in_bounds_gep( + key_datas.get_type(), + key_datas, + &[self.native_i8(i.try_into().unwrap())], + "", + ) + .unwrap() }; - self.builder.build_store(key_data, key_data_value); + self.builder.build_store(key_data, key_data_value).unwrap(); let key_length = unsafe { - self.builder.build_in_bounds_gep( - key_lengths, - &[self.native_i8(i.try_into().unwrap())], - "", - ) + self.builder + .build_in_bounds_gep( + key_lengths.get_type(), + key_lengths, + &[self.native_i8(i.try_into().unwrap())], + "", + ) + .unwrap() }; - self.builder.build_store(key_length, key_data_len); + self.builder.build_store(key_length, key_data_len).unwrap(); } // extra_args let extra_args_count = path.extra_args.len(); let extra_args_count_value = self.i32_value(extra_args_count as u64); - let extra_args_array = self.builder.build_array_alloca( - self.i32_type(), - self.native_i8(extra_args_count.try_into().unwrap()), - "", - ); + let extra_args_array = self + .builder + .build_array_alloca( + self.i32_type(), + self.native_i8(extra_args_count.try_into().unwrap()), + "", + ) + .unwrap(); for (i, &extra_arg) in path.extra_args.iter().enumerate() { let extra_arg_data = unsafe { - self.builder.build_in_bounds_gep( - extra_args_array, - &[self.native_i8(i.try_into().unwrap())], - "", - ) + self.builder + .build_in_bounds_gep( + extra_args_array.get_type(), + extra_args_array, + &[self.native_i8(i.try_into().unwrap())], + "", + ) + .unwrap() }; let extra_arg_value = self.i32_value(extra_arg as u64); - self.builder.build_store(extra_arg_data, extra_arg_value); + self.builder + .build_store(extra_arg_data, extra_arg_value) + .unwrap(); } ( key_count, @@ -261,14 +282,17 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { .into_int_value() }; - let is_empty = self.builder.build_int_compare( - IntPredicate::EQ, - length, - self.i32_value(DATA_EMPTY_LENGTH as u64).into_int_value(), - "", - ); + let is_empty = self + .builder + .build_int_compare( + IntPredicate::EQ, + length, + self.i32_value(DATA_EMPTY_LENGTH as u64).into_int_value(), + "", + ) + .unwrap(); - let value_ptr = self.builder.build_alloca(self.llvm_type(ty), ""); + let value_ptr = self.builder.build_alloca(self.llvm_type(ty), "").unwrap(); let then_block = self.append_block("default value"); let else_block = self.append_block("read storage object"); @@ -279,7 +303,7 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { // Check if storage path has exceeded index self.build_void_call("assert_storage_array_index", &[path_ptr]); let then_value = self.type_default_value(ty); - self.builder.build_store(value_ptr, then_value); + self.builder.build_store(value_ptr, then_value).unwrap(); self.br(end_block); self.builder.position_at_end(else_block); let data = self @@ -287,7 +311,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { .into_pointer_value(); let data = unsafe { self.builder - .build_in_bounds_gep(data, &[self.native_i8(0)], "") + .build_in_bounds_gep(data.get_type(), data, &[self.native_i8(0)], "") + .unwrap() .into() }; @@ -303,10 +328,13 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { } let else_value = self.ssz_decode_with_version(ty, ssz_info, data, length.into()); - self.builder.build_store(value_ptr, else_value); + self.builder.build_store(value_ptr, else_value).unwrap(); self.br(end_block); self.builder.position_at_end(end_block); - Ok(self.builder.build_load(value_ptr, "")) + Ok(self + .builder + .build_load(value_ptr.get_type(), value_ptr, "") + .unwrap()) } pub fn write_storage_object( diff --git a/smart_ir/src/ir_codegen/traits/builder.rs b/smart_ir/src/ir_codegen/traits/builder.rs index 7d32455..ab2c5b1 100644 --- a/smart_ir/src/ir_codegen/traits/builder.rs +++ b/smart_ir/src/ir_codegen/traits/builder.rs @@ -16,7 +16,7 @@ pub trait BuilderMethods: BackendTypes { /// SSA cond br instruction. fn cond_br(&self, cond: Self::Value, then_bb: Self::BasicBlock, else_bb: Self::BasicBlock); /// SSA load instruction. - fn load(&self, ptr: Self::Value, name: &str) -> Self::Value; + fn load(&self, pointee_ty: Self::Type, ptr: Self::Value, name: &str) -> Self::Value; /// SSA cast int to pointer. fn int_to_ptr(&self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; /// SSA bit cast. diff --git a/smart_ir/src/ir_codegen/ty.rs b/smart_ir/src/ir_codegen/ty.rs index 2f93357..e6e4ee2 100644 --- a/smart_ir/src/ir_codegen/ty.rs +++ b/smart_ir/src/ir_codegen/ty.rs @@ -6,7 +6,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, FunctionType, VoidType}; use inkwell::values::BasicValueEnum; use super::builtin_constants::{ - Q_HASHTBL_OBJ_S, Q_MAP_NEW_FUNC_NAME, Q_VECTOR_OBJ_S, Q_VEC_NEW_FUNC_NAME, + Q_HASHTBL_ITER, Q_MAP_NEW_FUNC_NAME, Q_VECTOR_ITER, Q_VEC_NEW_FUNC_NAME, RUNTIME_CONTEXT_LLVM_TY, VECTOR_NEW_FUNC_NAME, }; use super::context::IR2LLVMCodeGenContext; @@ -17,9 +17,9 @@ use crate::ir_codegen::traits::{BaseTypeMethods, BuilderMethods}; use crate::ir::cfg::{BuiltinType, FunctionDefinition, IntType, PrimitiveType, Type}; use crate::ir::metadata::ssz_info::SSZInfo; -const VEC_LLVM_TY: &str = "struct.vector"; -const Q_VEC_LLVM_TY: &str = "struct.qvector_s"; -const Q_MAP_LLVM_TY: &str = "struct.qhashtbl_s"; +pub const VEC_LLVM_TY: &str = "struct.vector"; +pub const Q_VEC_LLVM_TY: &str = "struct.qvector_s"; +pub const Q_MAP_LLVM_TY: &str = "struct.qhashtbl_s"; /// Impl TypedResultWalker for LLVMCodeGenContext to visit AST nodes to emit LLVM IR. impl<'ctx> IR2LLVMCodeGenContext<'ctx> { @@ -36,11 +36,13 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { IntType::I32 => self.i32_type(), IntType::I64 => self.i64_type(), IntType::I128 => self.llvm_context.i128_type().into(), + IntType::I256 => self.llvm_context.custom_width_int_type(256).into(), IntType::U8 => self.i8_type(), IntType::U16 => self.llvm_context.i16_type().into(), IntType::U32 => self.i32_type(), IntType::U64 => self.i64_type(), IntType::U128 => self.llvm_context.i128_type().into(), + IntType::U256 => self.llvm_context.custom_width_int_type(256).into(), }, }, Type::Map { key: _, value: _ } => self.ptr_type_to( @@ -68,67 +70,19 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { Type::Pointer(ptr) => self.ptr_type_to(self.llvm_type(ptr)), Type::Def(def) => self.llvm_type(&def.ty), Type::Builtin(builtin_ty) => match builtin_ty { - BuiltinType::VectorIter => - /* - struct.vector.iter { - struct.qvector_s* vec, - struct.qvector_obj_s* obj, - } - */ - { - self.ptr_type_to( - self.llvm_context - .struct_type( - &[ - self.ptr_type_to( - self.module - .get_struct_type(Q_VEC_LLVM_TY) - .expect(INTERNAL_ERROR_MSG) - .into(), - ), - self.ptr_type_to( - self.module - .get_struct_type(Q_VECTOR_OBJ_S) - .expect(INTERNAL_ERROR_MSG) - .into(), - ), - ], - true, - ) - .into(), - ) - } + BuiltinType::VectorIter => self.ptr_type_to( + self.module + .get_struct_type(Q_VECTOR_ITER) + .expect(INTERNAL_ERROR_MSG) + .into(), + ), - BuiltinType::MapIter => - /* - struct.map.iter { - struct.qhashtbl_s* map, - struct.qhashtbl_obj_s* obj, - } - */ - { - self.ptr_type_to( - self.llvm_context - .struct_type( - &[ - self.ptr_type_to( - self.module - .get_struct_type(Q_MAP_LLVM_TY) - .expect(INTERNAL_ERROR_MSG) - .into(), - ), - self.ptr_type_to( - self.module - .get_struct_type(Q_HASHTBL_OBJ_S) - .expect(INTERNAL_ERROR_MSG) - .into(), - ), - ], - true, - ) - .into(), - ) - } + BuiltinType::MapIter => self.ptr_type_to( + self.module + .get_struct_type(Q_HASHTBL_ITER) + .expect(INTERNAL_ERROR_MSG) + .into(), + ), BuiltinType::Parampack => self.vec_ptr_type(), BuiltinType::StoragePath => self.i32_type(), }, @@ -202,17 +156,21 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { let ptr = self.ptr_cast(s.into(), self.ptr_type_to(llvm_ty)); for (i, field_ty) in fields.iter().enumerate() { let field = unsafe { - self.builder.build_gep( - ptr.into_pointer_value(), - &[ - self.llvm_context.i32_type().const_zero(), - self.llvm_context.i32_type().const_int(i as u64, false), - ], - "", - ) + self.builder + .build_gep( + ptr.get_type(), + ptr.into_pointer_value(), + &[ + self.llvm_context.i32_type().const_zero(), + self.llvm_context.i32_type().const_int(i as u64, false), + ], + "", + ) + .unwrap() }; self.builder - .build_store(field, self.type_default_value(&field_ty.ty)); + .build_store(field, self.type_default_value(&field_ty.ty)) + .unwrap(); } ptr } @@ -220,7 +178,8 @@ impl<'ctx> IR2LLVMCodeGenContext<'ctx> { Type::Builtin(_) => unimplemented!(), _ => { self.builder - .build_store(s, self.type_default_value(elem_ty)); + .build_store(s, self.type_default_value(elem_ty)) + .unwrap(); s.into() } } diff --git a/smart_ir/src/runtime/stdlib/cJSON.c b/smart_ir/src/runtime/stdlib/cJSON.c index d0aa793..1bb528a 100644 --- a/smart_ir/src/runtime/stdlib/cJSON.c +++ b/smart_ir/src/runtime/stdlib/cJSON.c @@ -24,6 +24,7 @@ /* JSON parser in C. */ /* disable warnings about old C89 functions in MSVC */ +#include "stdlib.h" #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) #define _CRT_SECURE_NO_DEPRECATE #endif @@ -73,7 +74,7 @@ #ifdef _WIN32 #define NAN sqrt(-1.0) #else -#define NAN 0.0/0.0 +#define NAN (0.0/0.0) #endif #endif @@ -105,11 +106,11 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) return item->valuestring; } -CJSON_PUBLIC(uint128_t) cJSON_GetNumberValue(const cJSON * const item) +CJSON_PUBLIC(uint256_t) cJSON_GetNumberValue(const cJSON * const item) { if (!cJSON_IsNumber(item)) { - return (uint128_t) NAN; + return (uint256_t) NAN; } return item->valuedouble; @@ -304,7 +305,7 @@ typedef struct /* Parse the input text to generate a number, and populate the result into item. */ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) { - uint128_t number = 0; + uint256_t number = 0; unsigned char *after_end = NULL; unsigned char number_c_string[64]; unsigned char decimal_point = get_decimal_point(); @@ -354,10 +355,10 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu number_c_string[i] = '\0'; if (number_c_string[0] == '+' || isdigit(number_c_string[0])) { - number = strtou128((const char*)number_c_string, (char**)&after_end, BASE); + number = strtou256((const char*)number_c_string, (char**)&after_end, BASE); } else { item->negsign = true; - number = strtoi128((const char*)number_c_string, (char**)&after_end, BASE); + number = strtoi256((const char*)number_c_string, (char**)&after_end, BASE); } if (number_c_string == after_end) @@ -374,19 +375,19 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu } /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(uint128_t) cJSON_SetNumberHelper(cJSON *object, uint128_t number) +CJSON_PUBLIC(uint256_t) cJSON_SetNumberHelper(cJSON *object, uint256_t number) { - if ((int128_t)number >= INT128_MAX) + if ((int256_t)number >= INT256_MAX) { - object->valueint = INT128_MAX; + object->valueint = INT256_MAX; } - else if (number <= (uint128_t)INT128_MIN) + else if (number <= (uint256_t)INT256_MIN) { - object->valueint = INT128_MIN; + object->valueint = INT256_MIN; } else { - object->valueint = (int128_t)number; + object->valueint = (int256_t)number; } return object->valuedouble = number; @@ -446,10 +447,9 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) /* make sure that offset is valid */ return NULL; } - - if ((int128_t)needed > INT128_MAX) + if ((int256_t)needed > INT256_MAX) { - /* sizes bigger than INT128_MAX are currently not supported */ + /* sizes bigger than INT256_MAX are currently not supported */ return NULL; } @@ -464,10 +464,10 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } /* calculate new buffer size */ - if ((int128_t)needed > (INT128_MAX / 2)) + if ((int256_t)needed > (INT256_MAX / (int256_t) 2)) { - /* overflow of int, use INT128_MAX if possible */ - if ((int128_t)needed <= INT128_MAX) + /* overflow of int, use INT256_MAX if possible */ + if ((int256_t)needed <= (int256_t)INT256_MAX) { newsize = INT32_MAX; } @@ -531,33 +531,34 @@ static void update_offset(printbuffer * const buffer) #ifndef DISABLE_FLOAT /* securely comparison of floating-point variables */ -static cJSON_bool compare_double(uint128_t a, uint128_t b) +static cJSON_bool compare_double(uint256_t a, uint256_t b) { - uint128_t maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + uint256_t maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); return (fabs(a - b) <= maxVal * DBL_EPSILON); } #endif /* securely comparison of integer variables */ -static cJSON_bool compare_int(uint128_t a, uint128_t b) +static cJSON_bool compare_int(uint256_t a, uint256_t b) { - uint128_t diff = a - b; - return diff == 0 ; + uint256_t diff = a - b; + return diff == (uint256_t) 0 ; } -static void i128tos(unsigned char *number_buffer, uint128_t decimal, size_t length) { +static void i256tos(unsigned char *number_buffer, uint256_t decimal, size_t length) { size_t neg_flag = 0; size_t i = 0; - int128_t signed_decimal = 0; - signed_decimal = (int128_t)decimal; - if ((int128_t)signed_decimal == (int128_t)INT128_MIN) { - signed_decimal = signed_decimal + 1; - number_buffer[length - 1] = -signed_decimal % 10 + '0' + 1; // should be '8' - signed_decimal /= 10; + int256_t signed_decimal = 0; + signed_decimal = (int256_t)decimal; + if ((int256_t)signed_decimal == (int256_t)INT256_MIN) { + signed_decimal = signed_decimal + (int256_t) 1; + uint256_t rem; + signed_decimal = div256_u256_rem(-signed_decimal, (int256_t)10, &rem); + number_buffer[length - 1] =(int256_t) rem + (int256_t)(int32_t)'0' + (int256_t)1; // should be '8' i = 1; } - if (signed_decimal < 0) { + if (signed_decimal < (int256_t) 0) { signed_decimal = -signed_decimal; (*number_buffer) = '-'; neg_flag = 1; @@ -565,17 +566,19 @@ static void i128tos(unsigned char *number_buffer, uint128_t decimal, size_t leng for (; i < ((size_t)length) - neg_flag; i++) { - number_buffer[length - i - 1] = signed_decimal % 10 + '0'; - signed_decimal /= 10; + uint256_t rem; + signed_decimal = div256_u256_rem(-signed_decimal, (int256_t)10, &rem); + number_buffer[length - i - 1] = (int256_t)rem + (int256_t) '0'; } } -static void u128tos(unsigned char *number_buffer, uint128_t decimal, size_t length) { +static void u256tos(unsigned char *number_buffer, uint256_t decimal, size_t length) { size_t i = 0; for (i = 0; i < ((size_t)length); i++) { - number_buffer[length - i - 1] = decimal % 10 + '0'; - decimal /= 10; + uint256_t rem; + decimal = div256_u256_rem(decimal, (uint256_t)10, &rem); + number_buffer[length - i - 1] = (int256_t)rem + (int256_t) '0'; } } @@ -584,14 +587,14 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out { unsigned char *output_pointer = NULL; #ifndef DISABLE_FLOAT - uint128_t d = item->valuedouble; + uint256_t d = item->valuedouble; #endif int length = 0; size_t i = 0; unsigned char number_buffer[64] = {0}; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); #ifndef DISABLE_FLOAT - uint128_t test = 0.0; + uint256_t test = 0.0; #endif if (output_buffer == NULL) @@ -604,7 +607,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out { length = sprintf((char*)number_buffer, "null"); } - else if(d == (uint128_t)item->valueint) + else if(d == (uint256_t)item->valueint) { length = sprintf((char*)number_buffer, "%d", item->valueint); } @@ -614,7 +617,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out length = sprintf((char*)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((uint128_t)test, d)) + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((uint256_t)test, d)) { /* If not, print with 17 decimal places of precision */ length = sprintf((char*)number_buffer, "%1.17g", d); @@ -622,11 +625,11 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } #else if (item->negsign) { - length = numlen((int128_t)item->valueint); - i128tos(number_buffer, item->valueint, length); + length = numlen((int256_t)item->valueint); + i256tos(number_buffer, item->valueint, length); } else { length = unumlen(item->valueint); - u128tos(number_buffer, item->valueint, length); + u256tos(number_buffer, item->valueint, length); } #endif @@ -2177,7 +2180,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const uint128_t number, bool sign) +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const uint256_t number, bool sign) { cJSON *number_item = cJSON_CreateNumber(number, sign); if (add_item_to_object(object, name, number_item, &global_hooks, false)) @@ -2479,10 +2482,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(uint128_t num, bool sign) +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(uint256_t num, bool sign) { cJSON *item = cJSON_New_Item(&global_hooks); - int128_t signnum = 0; + int256_t signnum = 0; if(item) { item->type = cJSON_Number; @@ -2491,9 +2494,9 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(uint128_t num, bool sign) item->negsign = sign; /* use saturation in case of overflow */ if (sign) { - signnum = (int128_t)num; - if (signnum >= 0) { - char msg[] = "JSON Number Overflow: signed number smaller than INT128_MIN"; + signnum = (int256_t)num; + if (signnum >= (int256_t) 0) { + char msg[] = "JSON Number Overflow: signed number smaller than INT256_MIN"; IR_ABORT(msg, sizeof(msg) - 1); } } @@ -2647,7 +2650,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) for(i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber((uint128_t)numbers[i], false); + n = cJSON_CreateNumber((uint256_t) (uint128_t)numbers[i], false); if(!n) { cJSON_Delete(a); @@ -2671,7 +2674,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const uint128_t *numbers, int count) +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const uint256_t *numbers, int count) { size_t i = 0; cJSON *n = NULL; diff --git a/smart_ir/src/runtime/stdlib/cJSON.h b/smart_ir/src/runtime/stdlib/cJSON.h index 90ce343..dcf851f 100644 --- a/smart_ir/src/runtime/stdlib/cJSON.h +++ b/smart_ir/src/runtime/stdlib/cJSON.h @@ -114,8 +114,8 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ #define strncmp __strncmp #define strcpy __strcpy #define isdigit __isdigit -#define strtoi128 __strtoi128 -#define strtou128 __strtou128 +#define strtoi256 __strtoi256 +#define strtou256 __strtou256 #else #include #include @@ -142,9 +142,9 @@ typedef struct cJSON /* The item's string, if type==cJSON_String and type == cJSON_Raw */ char *valuestring; /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - uint128_t valueint; + uint256_t valueint; /* The item's number, if type==cJSON_Number */ - int128_t valuedouble; + int256_t valuedouble; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ char *string; @@ -200,12 +200,10 @@ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); /* Check item type and return its value */ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); -CJSON_PUBLIC(uint128_t) cJSON_GetNumberValue(const cJSON * const item); +CJSON_PUBLIC(uint256_t) cJSON_GetNumberValue(const cJSON * const item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); @@ -224,7 +222,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(uint128_t num, bool sign); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(uint256_t num, bool sign); CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); /* raw json */ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); @@ -243,7 +241,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const uint128_t *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const uint256_t *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); /* Append item to the specified array/object. */ @@ -293,7 +291,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * co CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const uint128_t number, bool sign); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const uint256_t number, bool sign); CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); @@ -302,8 +300,8 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c /* When assigning an integer value, it needs to be propagated to valuedouble too. */ #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) /* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(uint128_t) cJSON_SetNumberHelper(cJSON *object, uint128_t number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (uint128_t)number) : (number)) +CJSON_PUBLIC(uint256_t) cJSON_SetNumberHelper(cJSON *object, uint256_t number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (uint256_t)number) : (number)) /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); diff --git a/smart_ir/src/runtime/stdlib/call_log.c b/smart_ir/src/runtime/stdlib/call_log.c index 27b84f5..57292bb 100644 --- a/smart_ir/src/runtime/stdlib/call_log.c +++ b/smart_ir/src/runtime/stdlib/call_log.c @@ -4,12 +4,6 @@ #include "./call_log.h" -extern void -log(int32_t topics, uint32_t topics_d1_length, uint32_t topics_length, - uint32_t desc, uint32_t desc_length); - -extern void -println(uint32_t src, uint32_t len); void ir_builtin_call_log(qvector_t *topics, qvector_t *desc) diff --git a/smart_ir/src/runtime/stdlib/call_log.h b/smart_ir/src/runtime/stdlib/call_log.h index 2f28106..a16a87a 100644 --- a/smart_ir/src/runtime/stdlib/call_log.h +++ b/smart_ir/src/runtime/stdlib/call_log.h @@ -20,6 +20,13 @@ ir_builtin_call_log(qvector_t *topics, qvector_t *desc); extern void ir_builtin_print(struct vector *str); +extern void +log(int32_t topics, uint32_t topics_d1_length, uint32_t topics_length, + uint32_t desc, uint32_t desc_length); + +extern void +println(uint32_t src, uint32_t len); + #ifdef __cplusplus } diff --git a/smart_ir/src/runtime/stdlib/data_stream.c b/smart_ir/src/runtime/stdlib/data_stream.c index 28091f8..8ca4921 100644 --- a/smart_ir/src/runtime/stdlib/data_stream.c +++ b/smart_ir/src/runtime/stdlib/data_stream.c @@ -163,11 +163,13 @@ DATA_STREAM_ENCODE_INT_DECLARE(u16, uint16_t) DATA_STREAM_ENCODE_INT_DECLARE(u32, uint32_t) DATA_STREAM_ENCODE_INT_DECLARE(u64, uint64_t) DATA_STREAM_ENCODE_INT_DECLARE(u128, uint128_t) +DATA_STREAM_ENCODE_INT_DECLARE(u256, uint256_t) DATA_STREAM_ENCODE_INT_DECLARE(i8, int8_t) DATA_STREAM_ENCODE_INT_DECLARE(i16, int16_t) DATA_STREAM_ENCODE_INT_DECLARE(i32, int32_t) DATA_STREAM_ENCODE_INT_DECLARE(i64, int64_t) DATA_STREAM_ENCODE_INT_DECLARE(i128, int128_t) +DATA_STREAM_ENCODE_INT_DECLARE(i256, int256_t) DATA_STREAM_DECODE_INT_DECLARE(bool, uint8_t) DATA_STREAM_DECODE_INT_DECLARE(u8, uint8_t) @@ -175,11 +177,13 @@ DATA_STREAM_DECODE_INT_DECLARE(u16, uint16_t) DATA_STREAM_DECODE_INT_DECLARE(u32, uint32_t) DATA_STREAM_DECODE_INT_DECLARE(u64, uint64_t) DATA_STREAM_DECODE_INT_DECLARE(u128, uint128_t) +DATA_STREAM_DECODE_INT_DECLARE(u256, uint256_t) DATA_STREAM_DECODE_INT_DECLARE(i8, int8_t) DATA_STREAM_DECODE_INT_DECLARE(i16, int16_t) DATA_STREAM_DECODE_INT_DECLARE(i32, int32_t) DATA_STREAM_DECODE_INT_DECLARE(i64, int64_t) DATA_STREAM_DECODE_INT_DECLARE(i128, int128_t) +DATA_STREAM_DECODE_INT_DECLARE(i256, int256_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(bool, bool) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u8, uint8_t) @@ -187,11 +191,13 @@ DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u16, uint16_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u32, uint32_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u64, uint64_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u128, uint128_t) +DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u256, uint256_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i8, int8_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i16, int16_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i32, int32_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i64, int64_t) DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i128, int128_t) +DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i256, int256_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(bool, uint8_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u8, uint8_t) @@ -199,11 +205,13 @@ DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u16, uint16_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u32, uint32_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u64, uint64_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u128, uint128_t) +DATA_STREAM_DECODE_INT_ARRAY_DECLARE(u256, uint256_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i8, int8_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i16, int16_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i32, int32_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i64, int64_t) DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i128, int128_t) +DATA_STREAM_DECODE_INT_ARRAY_DECLARE(i256, int256_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(bool, bool) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u8, uint8_t) @@ -211,11 +219,13 @@ DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u16, uint16_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u32, uint32_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u64, uint64_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u128, uint128_t) +DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u256, uint256_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i8, int8_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i16, int16_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i32, int32_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i64, int64_t) DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i128, int128_t) +DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i256, int256_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(bool, uint8_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u8, uint8_t) @@ -223,11 +233,13 @@ DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u16, uint16_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u32, uint32_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u64, uint64_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u128, uint128_t) +DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(u256, uint256_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i8, int8_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i16, int16_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i32, int32_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i64, int64_t) DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i128, int128_t) +DATA_STREAM_DECODE_STR_INT_MAP_DECLARE(i256, int256_t) int32_t data_stream_encode_str(const struct vector *v, uint8_t *buf, int32_t offset) @@ -404,15 +416,17 @@ qhashtbl_total_space(qhashtbl_t *v) case IR_RUNTIME_TYPE_U32: str_n = 4; break; case IR_RUNTIME_TYPE_U64: str_n = 8; break; case IR_RUNTIME_TYPE_U128: str_n = 16; break; + case IR_RUNTIME_TYPE_U256: str_n = 32; break; case IR_RUNTIME_TYPE_I8: str_n = 1; break; case IR_RUNTIME_TYPE_I16: str_n = 2; break; case IR_RUNTIME_TYPE_I32: str_n = 4; break; case IR_RUNTIME_TYPE_I64: str_n = 8; break; case IR_RUNTIME_TYPE_I128: str_n = 16; break; + case IR_RUNTIME_TYPE_I256: str_n = 32; break; default: { char msg[] = "invalid map int key type"; IR_ABORT(msg, sizeof(msg) - 1); - return NULL; + return 0; } } } else { diff --git a/smart_ir/src/runtime/stdlib/data_stream.h b/smart_ir/src/runtime/stdlib/data_stream.h index b921b7b..8636605 100644 --- a/smart_ir/src/runtime/stdlib/data_stream.h +++ b/smart_ir/src/runtime/stdlib/data_stream.h @@ -45,6 +45,11 @@ extern int32_t data_stream_decode_u128(__uint128_t *v, uint8_t *buf, int32_t offset, int32_t len); extern int32_t +data_stream_encode_u256(uint256_t v, uint8_t *buf, int32_t offset); +extern int32_t +data_stream_decode_u256(uint256_t *v, uint8_t *buf, int32_t offset, + int32_t len); +extern int32_t data_stream_encode_i8(int8_t v, uint8_t *buf, int32_t offset); extern int32_t data_stream_decode_i8(int8_t *v, uint8_t *buf, int32_t offset, int32_t len); @@ -65,6 +70,11 @@ data_stream_encode_i128(__int128_t v, uint8_t *buf, int32_t offset); extern int32_t data_stream_decode_i128(__int128_t *v, uint8_t *buf, int32_t offset, int32_t len); +extern int32_t +data_stream_encode_i256(int256_t v, uint8_t *buf, int32_t offset); +extern int32_t +data_stream_decode_i256(int256_t *v, uint8_t *buf, int32_t offset, + int32_t len); extern int32_t data_stream_encode_str(const struct vector *v, uint8_t *buf, int32_t offset); @@ -122,6 +132,12 @@ extern int32_t data_stream_decode_u128array(qvector_t *v, uint8_t *buf, int32_t offset, int32_t len); extern int32_t +data_stream_encode_u256array(qvector_t *v, uint8_t *buf, int32_t offset, + struct RuntimeContext *ctx); +extern int32_t +data_stream_decode_u256array(qvector_t *v, uint8_t *buf, int32_t offset, + int32_t len); +extern int32_t data_stream_encode_i8array(qvector_t *v, uint8_t *buf, int32_t offset, struct RuntimeContext *ctx); extern int32_t @@ -151,6 +167,12 @@ data_stream_encode_i128array(qvector_t *v, uint8_t *buf, int32_t offset, extern int32_t data_stream_decode_i128array(qvector_t *v, uint8_t *buf, int32_t offset, int32_t len); +extern int32_t +data_stream_encode_i256array(qvector_t *v, uint8_t *buf, int32_t offset, + struct RuntimeContext *ctx); +extern int32_t +data_stream_decode_i256array(qvector_t *v, uint8_t *buf, int32_t offset, + int32_t len); /* Map */ extern int32_t @@ -184,6 +206,11 @@ extern int32_t data_stream_decode_stru128map(qhashtbl_t *v, uint8_t *buf, int32_t offset, int32_t len); extern int32_t +data_stream_encode_stru256map(qhashtbl_t *v, uint8_t *buf, int32_t offset); +extern int32_t +data_stream_decode_stru256map(qhashtbl_t *v, uint8_t *buf, int32_t offset, + int32_t len); +extern int32_t data_stream_encode_stri8map(qhashtbl_t *v, uint8_t *buf, int32_t offset); extern int32_t data_stream_decode_stri8map(qhashtbl_t *v, uint8_t *buf, int32_t offset, @@ -209,6 +236,11 @@ extern int32_t data_stream_decode_stri128map(qhashtbl_t *v, uint8_t *buf, int32_t offset, int32_t len); extern int32_t +data_stream_encode_stri256map(qhashtbl_t *v, uint8_t *buf, int32_t offset); +extern int32_t +data_stream_decode_stri256map(qhashtbl_t *v, uint8_t *buf, int32_t offset, + int32_t len); +extern int32_t data_stream_encode_strstrmap(qhashtbl_t *v, uint8_t *buf, int32_t offset); extern int32_t data_stream_decode_strstrmap(qhashtbl_t *v, uint8_t *buf, int32_t offset, diff --git a/smart_ir/src/runtime/stdlib/data_stream_builtin.c b/smart_ir/src/runtime/stdlib/data_stream_builtin.c index 802f8ae..a720a19 100644 --- a/smart_ir/src/runtime/stdlib/data_stream_builtin.c +++ b/smart_ir/src/runtime/stdlib/data_stream_builtin.c @@ -89,11 +89,13 @@ BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(u16, uint16_t, 2) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(u32, uint32_t, 4) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(u64, uint64_t, 8) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(u128, uint128_t, 16) +BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(u256, uint256_t, 32) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i8, int8_t, 1) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i16, int16_t, 2) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i32, int32_t, 4) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i64, int64_t, 8) BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i128, int128_t, 16) +BUILTIN_DATA_STREAM_ENCODE_INT_DECLARE(i256, int256_t, 32) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(bool) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u8) @@ -101,11 +103,13 @@ BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u16) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u32) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u64) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u128) +BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(u256) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i8) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i16) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i32) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i64) BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i128) +BUILTIN_DATA_STREAM_ENCODE_INT_ARRAY_DECLARE(i256) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(bool) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u8) @@ -113,11 +117,13 @@ BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u16) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u32) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u64) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u128) +BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(u256) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i8) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i16) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i32) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i64) BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i128) +BUILTIN_DATA_STREAM_ENCODE_STR_INT_MAP_DECLARE(i256) qvector_t *ir_builtin_data_stream_encode_strstrmap(qhashtbl_t *in) { diff --git a/smart_ir/src/runtime/stdlib/data_stream_builtin.h b/smart_ir/src/runtime/stdlib/data_stream_builtin.h index 1481608..facdd00 100644 --- a/smart_ir/src/runtime/stdlib/data_stream_builtin.h +++ b/smart_ir/src/runtime/stdlib/data_stream_builtin.h @@ -27,6 +27,8 @@ ir_builtin_data_stream_encode_u64(uint64_t value); extern qvector_t * ir_builtin_data_stream_encode_u128(__uint128_t value); extern qvector_t * +ir_builtin_data_stream_encode_u256(uint256_t value); +extern qvector_t * ir_builtin_data_stream_encode_i8(int8_t value); extern qvector_t * ir_builtin_data_stream_encode_i16(int16_t value); @@ -37,6 +39,8 @@ ir_builtin_data_stream_encode_i64(int64_t value); extern qvector_t * ir_builtin_data_stream_encode_i128(__int128_t value); extern qvector_t * +ir_builtin_data_stream_encode_i256(int256_t value); +extern qvector_t * ir_builtin_data_stream_encode_str(const struct vector *value); /* Array */ @@ -55,6 +59,8 @@ ir_builtin_data_stream_encode_u64array(qvector_t *v); extern qvector_t * ir_builtin_data_stream_encode_u128array(qvector_t *v); extern qvector_t * +ir_builtin_data_stream_encode_u256array(qvector_t *v); +extern qvector_t * ir_builtin_data_stream_encode_i8array(qvector_t *v); extern qvector_t * ir_builtin_data_stream_encode_i16array(qvector_t *v); @@ -64,6 +70,8 @@ extern qvector_t * ir_builtin_data_stream_encode_i64array(qvector_t *v); extern qvector_t * ir_builtin_data_stream_encode_i128array(qvector_t *v); +extern qvector_t * +ir_builtin_data_stream_encode_i256array(qvector_t *v); /* Map */ extern qvector_t * @@ -79,6 +87,8 @@ ir_builtin_data_stream_encode_stru64map(qhashtbl_t *value); extern qvector_t * ir_builtin_data_stream_encode_stru128map(qhashtbl_t *value); extern qvector_t * +ir_builtin_data_stream_encode_stru256map(qhashtbl_t *value); +extern qvector_t * ir_builtin_data_stream_encode_stri8map(qhashtbl_t *value); extern qvector_t * ir_builtin_data_stream_encode_stri16map(qhashtbl_t *value); @@ -89,6 +99,8 @@ ir_builtin_data_stream_encode_stri64map(qhashtbl_t *value); extern qvector_t * ir_builtin_data_stream_encode_stri128map(qhashtbl_t *value); extern qvector_t * +ir_builtin_data_stream_encode_stri256map(qhashtbl_t *value); +extern qvector_t * ir_builtin_data_stream_encode_strstrmap(qhashtbl_t *value); #ifdef __cplusplus diff --git a/smart_ir/src/runtime/stdlib/ir_type.c b/smart_ir/src/runtime/stdlib/ir_type.c index a732f8f..8f8a30d 100644 --- a/smart_ir/src/runtime/stdlib/ir_type.c +++ b/smart_ir/src/runtime/stdlib/ir_type.c @@ -62,6 +62,9 @@ void ir_builtin_print_type(uint32_t runtime_class_offset) case IR_RUNTIME_TYPE_U128: { println("u128", 4); } break; + case IR_RUNTIME_TYPE_U256: { + println("i256", 4); + } break; case IR_RUNTIME_TYPE_I8: { println("i8", 2); } break; @@ -77,6 +80,9 @@ void ir_builtin_print_type(uint32_t runtime_class_offset) case IR_RUNTIME_TYPE_I128: { println("i128", 4); } break; + case IR_RUNTIME_TYPE_I256: { + println("i256", 4); + } break; case IR_RUNTIME_TYPE_BOOL: { println("bool", 4); } break; @@ -93,7 +99,7 @@ void ir_builtin_print_type(uint32_t runtime_class_offset) struct vector *fields_name_ptr = (struct vector *)(all_runtimes_classes_address + fields_name_offset); uint32_t fields_name_bytes_offset = (uint32_t)fields_name_ptr->data; uint32_t field_name_bytes = all_runtimes_classes_address + fields_name_bytes_offset; - println(field_name_bytes, fields_name_ptr->len); + println((const char *)field_name_bytes, fields_name_ptr->len); uint32_t field_offset = fields_offsets_array[i]; ir_builtin_print_type(field_offset); } @@ -108,7 +114,7 @@ void ir_builtin_print_type(uint32_t runtime_class_offset) struct vector *fields_name_ptr = (struct vector *)(all_runtimes_classes_address + fields_name_offset); uint32_t fields_name_bytes_offset = (uint32_t)fields_name_ptr->data; int32_t field_name_bytes = all_runtimes_classes_address + fields_name_bytes_offset; - println(field_name_bytes, fields_name_ptr->len); + println((const char *)field_name_bytes, fields_name_ptr->len); uint32_t field_offset = fields_offsets_array[i]; ir_builtin_print_type(field_offset); } @@ -118,7 +124,7 @@ void ir_builtin_print_type(uint32_t runtime_class_offset) println("array", 5); println("size:", 5); char *array_size = builtin_i32_toa(runtime_class->array_size, 10); - println((int32_t)array_size, __strlen(array_size)); + println(array_size, __strlen(array_size)); } else { println("vector", 6); } @@ -162,6 +168,9 @@ get_ir_type_size_as_element(struct IRRuntimeClass *runtime_class) case IR_RUNTIME_TYPE_U128: { return 16; } break; + case IR_RUNTIME_TYPE_U256: { + return 32; + } break; case IR_RUNTIME_TYPE_I8: { return 1; } break; @@ -177,6 +186,9 @@ get_ir_type_size_as_element(struct IRRuntimeClass *runtime_class) case IR_RUNTIME_TYPE_I128: { return 16; } break; + case IR_RUNTIME_TYPE_I256: { + return 32; + } break; case IR_RUNTIME_TYPE_BOOL: { return 1; } break; @@ -220,6 +232,9 @@ size_t calculate_ir_type_size(struct IRRuntimeClass *runtime_class) { case IR_RUNTIME_TYPE_U128: { return 16; } break; + case IR_RUNTIME_TYPE_U256: { + return 32; + } break; case IR_RUNTIME_TYPE_I8: { return 1; } break; @@ -235,6 +250,9 @@ size_t calculate_ir_type_size(struct IRRuntimeClass *runtime_class) { case IR_RUNTIME_TYPE_I128: { return 16; } break; + case IR_RUNTIME_TYPE_I256: { + return 32; + } break; case IR_RUNTIME_TYPE_BOOL: { return 1; } break; @@ -306,6 +324,11 @@ ir_builtin_create_ir_value(uint32_t runtime_class_offset) uint64_t* value = (uint64_t*) __malloc(sizeof(uint64_t[2])); __memset(value, sizeof(uint64_t[2]), 0); return (void*) value; + } break; + case IR_RUNTIME_TYPE_U256: { + uint64_t* value = (uint64_t*) __malloc(sizeof(uint64_t[4])); + __memset(value, sizeof(uint64_t[4]), 0); + return (void*) value; } break; case IR_RUNTIME_TYPE_I8: { return (void*) 0; @@ -325,6 +348,11 @@ ir_builtin_create_ir_value(uint32_t runtime_class_offset) __memset(value, sizeof(uint64_t[2]), 0); return (void*) value; } break; + case IR_RUNTIME_TYPE_I256: { + uint64_t* value = (uint64_t*) __malloc(sizeof(uint64_t[4])); + __memset(value, sizeof(uint64_t[4]), 0); + return (void*) value; + } break; case IR_RUNTIME_TYPE_BOOL: { return (void*) 0; } break; @@ -417,6 +445,9 @@ is_pointer_type(uint32_t runtime_class_offset) { return false; // pointer } break; + case IR_RUNTIME_TYPE_U256: { + return false; // pointer + } break; case IR_RUNTIME_TYPE_I8: { return false; @@ -437,6 +468,9 @@ is_pointer_type(uint32_t runtime_class_offset) { return false; // pointer } break; + case IR_RUNTIME_TYPE_I256: { + return false; // pointer + } break; case IR_RUNTIME_TYPE_BOOL: { return false; diff --git a/smart_ir/src/runtime/stdlib/ir_type.h b/smart_ir/src/runtime/stdlib/ir_type.h index 70018c2..dd04aa0 100644 --- a/smart_ir/src/runtime/stdlib/ir_type.h +++ b/smart_ir/src/runtime/stdlib/ir_type.h @@ -18,22 +18,24 @@ typedef enum IRRuntimeType { IR_RUNTIME_TYPE_U32 = 2, IR_RUNTIME_TYPE_U64 = 3, IR_RUNTIME_TYPE_U128 = 4, - - IR_RUNTIME_TYPE_I8 = 5, - IR_RUNTIME_TYPE_I16 = 6, - IR_RUNTIME_TYPE_I32 = 7, - IR_RUNTIME_TYPE_I64 = 8, - IR_RUNTIME_TYPE_I128 = 9, - - IR_RUNTIME_TYPE_BOOL = 10, - IR_RUNTIME_TYPE_STR = 11, - IR_RUNTIME_TYPE_ASSET = 12, - IR_RUNTIME_TYPE_STRUCT = 13, - IR_RUNTIME_TYPE_ARRAY = 14, - IR_RUNTIME_TYPE_MAP = 15 + IR_RUNTIME_TYPE_U256 = 5, + + IR_RUNTIME_TYPE_I8 = 6, + IR_RUNTIME_TYPE_I16 = 7, + IR_RUNTIME_TYPE_I32 = 8, + IR_RUNTIME_TYPE_I64 = 9, + IR_RUNTIME_TYPE_I128 = 10, + IR_RUNTIME_TYPE_I256 = 11, + + IR_RUNTIME_TYPE_BOOL = 12, + IR_RUNTIME_TYPE_STR = 13, + IR_RUNTIME_TYPE_ASSET = 14, + IR_RUNTIME_TYPE_STRUCT = 15, + IR_RUNTIME_TYPE_ARRAY = 16, + IR_RUNTIME_TYPE_MAP = 17 } IRRuntimeType; -#define IRRuntimeIntegerTypeMaxEnum IR_RUNTIME_TYPE_I128 +#define IRRuntimeIntegerTypeMaxEnum IR_RUNTIME_TYPE_I256 inline bool __attribute__((artificial)) __attribute__((always_inline)) @@ -97,6 +99,8 @@ get_ptr_of_ptr_value(uint32_t runtime_class_offset, void *val); void * get_array_elem_ptr_at_idx(uint32_t runtime_class_offset, void *val, uint32_t idx); +// Get the real malloc size of the ir-type value +size_t calculate_ir_type_size(struct IRRuntimeClass *runtime_class); #ifdef __cplusplus } // end "C" diff --git a/smart_ir/src/runtime/stdlib/json.c b/smart_ir/src/runtime/stdlib/json.c index 6eec45f..57cee8a 100644 --- a/smart_ir/src/runtime/stdlib/json.c +++ b/smart_ir/src/runtime/stdlib/json.c @@ -50,7 +50,7 @@ cjson_to_ir_type(uint32_t runtime_class_offset, cJSON *obj); cJSON *ir_builtin_json_encode_##id(void *val) \ { \ ty v = *(ty *)val; \ - cJSON *ret = cJSON_CreateNumber((uint128_t)v, v < 0); \ + cJSON *ret = cJSON_CreateNumber((uint256_t)v, (uint256_t) v < (uint256_t) 0); \ return ret; \ } @@ -67,12 +67,14 @@ IR_BUILTIN_JSON_ENCODE_INT_DECLARE(u16, uint16_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(u32, uint32_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(u64, uint64_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(u128, uint128_t) +IR_BUILTIN_JSON_ENCODE_INT_DECLARE(u256, uint256_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i8, int8_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i16, int16_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i32, int32_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i64, int64_t) IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i128, int128_t) +IR_BUILTIN_JSON_ENCODE_INT_DECLARE(i256, int256_t) cJSON * ir_builtin_json_encode_str(void *val) @@ -163,7 +165,7 @@ ir_builtin_json_encode_map(uint32_t runtime_class_offset, void *val) while (qhashtbl_getnext(v, &item, true)) { void *val_ptr = get_data_ptr_of_ptr_value(runtime_class->map_value_ty, item.data); - char *key = item.key; + char *key = (char *)item.key; if (TABLE_KEY_IS_INT(v)) { key = builtin_i64_toa(item.key, 10); } @@ -204,6 +206,10 @@ ir_type_to_cjson(uint32_t runtime_class_offset, void *val) { return ir_builtin_json_encode_u128(val); } break; + case IR_RUNTIME_TYPE_U256: + { + return ir_builtin_json_encode_u256(val); + } break; case IR_RUNTIME_TYPE_I8: { return ir_builtin_json_encode_i8(val); @@ -224,6 +230,10 @@ ir_type_to_cjson(uint32_t runtime_class_offset, void *val) { return ir_builtin_json_encode_i128(val); } break; + case IR_RUNTIME_TYPE_I256: + { + return ir_builtin_json_encode_i256(val); + } break; case IR_RUNTIME_TYPE_BOOL: { return ir_builtin_json_encode_bool(val); @@ -295,12 +305,14 @@ IR_BUILTIN_JSON_DECODE_INT_DECLARE(u16, uint16_t, 2, false) IR_BUILTIN_JSON_DECODE_INT_DECLARE(u32, uint32_t, 4, false) IR_BUILTIN_JSON_DECODE_INT_DECLARE(u64, uint64_t, 8, false) IR_BUILTIN_JSON_DECODE_INT_DECLARE(u128, uint128_t, 16, false) +IR_BUILTIN_JSON_DECODE_INT_DECLARE(u256, uint256_t, 32, false) IR_BUILTIN_JSON_DECODE_INT_DECLARE(i8, int8_t, 1, true) IR_BUILTIN_JSON_DECODE_INT_DECLARE(i16, int16_t, 2, true) IR_BUILTIN_JSON_DECODE_INT_DECLARE(i32, int32_t, 4, true) IR_BUILTIN_JSON_DECODE_INT_DECLARE(i64, int64_t, 8, true) IR_BUILTIN_JSON_DECODE_INT_DECLARE(i128, int128_t, 16, true) +IR_BUILTIN_JSON_DECODE_INT_DECLARE(i256, int256_t, 32, true) void * ir_builtin_json_decode_str(cJSON *obj) @@ -432,14 +444,14 @@ ir_builtin_json_decode_map(uint32_t runtime_class_offset, cJSON *obj) char *key = elem->string; if (TABLE_KEY_IS_INT(ret)) { struct vector *int_str = vector_new(__strlen(key), 1, key); - if (ret->key_runtime_ty <= IR_RUNTIME_TYPE_U128) { - key = (int64_t)ir_builtin_str_to_u128(int_str); + if (ret->key_runtime_ty <= IR_RUNTIME_TYPE_U256) { + key = (char *)ir_builtin_str_to_u256(int_str); } else { - key = (int64_t)ir_builtin_str_to_i128(int_str); + key = (char *)ir_builtin_str_to_i256(int_str); } } - qhashtbl_put(ret, key, (void *)item, + qhashtbl_put(ret,(int64_t) key, (void *)item, get_ir_type_size_as_element(value_ty)); } return (void *)ret; @@ -474,6 +486,10 @@ cjson_to_ir_type(uint32_t runtime_class_offset, cJSON *obj) { return ir_builtin_json_decode_u128(obj); } break; + case IR_RUNTIME_TYPE_U256: + { + return ir_builtin_json_decode_u256(obj); + } break; case IR_RUNTIME_TYPE_I8: { return ir_builtin_json_decode_i8(obj); @@ -494,6 +510,10 @@ cjson_to_ir_type(uint32_t runtime_class_offset, cJSON *obj) { return ir_builtin_json_decode_i128(obj); } break; + case IR_RUNTIME_TYPE_I256: + { + return ir_builtin_json_decode_i256(obj); + } break; case IR_RUNTIME_TYPE_BOOL: { return ir_builtin_json_decode_bool(obj); diff --git a/smart_ir/src/runtime/stdlib/makefile b/smart_ir/src/runtime/stdlib/makefile index c0c0d5b..94be8e3 100644 --- a/smart_ir/src/runtime/stdlib/makefile +++ b/smart_ir/src/runtime/stdlib/makefile @@ -1,5 +1,5 @@ CC=clang -CFLAGS=$(TARGET_FLAGS) -emit-llvm -O3 -ffreestanding -fno-builtin -Wall -Wno-unused-function -ftrapv -v +CFLAGS=$(TARGET_FLAGS) -emit-llvm -O3 -Xclang -fexperimental-max-bitint-width=256 -ffreestanding -fno-builtin -Wall -Wno-unused-function -ftrapv -v wasm/%.bc: %.c $(CC) -c $(CFLAGS) $< -o $@ diff --git a/smart_ir/src/runtime/stdlib/math.c b/smart_ir/src/runtime/stdlib/math.c index 2e3c403..b2899d1 100644 --- a/smart_ir/src/runtime/stdlib/math.c +++ b/smart_ir/src/runtime/stdlib/math.c @@ -52,6 +52,8 @@ POW_INT_DECLARE(u64, uint64_t); POW_INT_DECLARE(u128, __uint128_t); +POW_INT_DECLARE(u256, uint256_t); + POW_INT_DECLARE(i8, int8_t); POW_INT_DECLARE(i16, int16_t); @@ -62,8 +64,10 @@ POW_INT_DECLARE(i64, int64_t); POW_INT_DECLARE(i128, __int128_t); +POW_INT_DECLARE(i256, int256_t); + // when num is negative, split to two parts to avoid int_min parsed to negative int -#define MAX_ITOA_STR_SIZE 128 +#define MAX_ITOA_STR_SIZE 256 #define INT_TO_A(id, ty, uty) \ char *builtin_##id##_toa(ty num, int radix) \ { \ @@ -73,24 +77,26 @@ POW_INT_DECLARE(i128, __int128_t); } \ char *str = (char *)__malloc(MAX_ITOA_STR_SIZE * sizeof(char)); \ char index[] = "0123456789abcdefghijklmnopqrstuvwxyz"; \ - uint128_t unum; \ + uint256_t unum; \ int i = 0, j, k; \ - if (radix == 10 && num < 0) { \ - ty num_first = num / 2; \ + if (radix == 10 && num < (ty) 0) { \ + ty num_first = num >> 1; \ ty num_second = num - num_first; \ - unum = ((uint128_t)-num_first) + ((uint128_t)-num_second); \ + unum = ((uint256_t)-num_first) + ((uint256_t)-num_second); \ str[i++] = '-'; \ } \ else { \ - unum = (uint128_t)(uty)num; \ + unum = (uint256_t)(uty)num; \ } \ do { \ if (i >= MAX_ITOA_STR_SIZE) { \ free(str); \ return NULL; \ } \ - str[i++] = index[unum % (unsigned)radix]; \ - unum /= radix; \ + uint256_t rem; \ + unum = div256_u256_rem(unum,(uint256_t)radix , &rem); \ + str[i++] = index[rem]; \ + \ } while (unum); \ \ str[i] = '\0'; \ @@ -122,6 +128,8 @@ INT_TO_A(i64, int64_t, uint64_t); INT_TO_A(i128, __int128_t, __uint128_t); +INT_TO_A(i256, int256_t, uint256_t); + INT_TO_A(u8, uint8_t,uint8_t); INT_TO_A(u16, uint16_t, uint16_t); @@ -132,6 +140,8 @@ INT_TO_A(u64, uint64_t, uint64_t); INT_TO_A(u128, __uint128_t, __uint128_t); +INT_TO_A(u256, uint256_t, uint256_t); + #define INT_TO_STR(id, ty) \ struct vector *ir_builtin_##id##_to_str(ty num, int radix) \ { \ @@ -149,6 +159,8 @@ INT_TO_STR(i64, int64_t); INT_TO_STR(i128, __int128_t); +INT_TO_STR(i256, int256_t); + INT_TO_STR(u8, uint8_t); INT_TO_STR(u16, uint16_t); @@ -159,6 +171,8 @@ INT_TO_STR(u64, uint64_t); INT_TO_STR(u128, __uint128_t); +INT_TO_STR(u256, uint256_t); + // this tmp result must use _target_unsigned_type, otherwise the negative min value decode will cause overflow // the for loop index i must be signed int to avoid loop // the final result parsed to result_first and result_second to avoid too large to parse to int type @@ -198,14 +212,14 @@ INT_TO_STR(u128, __uint128_t); return result; \ } \ uint32_t digit_int = digit - '0'; \ - _target_unsigned_type new_result = result + (digit_multiply * digit_int); \ + _target_unsigned_type new_result = result + (digit_multiply * (_target_unsigned_type) digit_int); \ if (new_result < result) { \ char msg[] = "str to int failed: overflow"; \ IR_ABORT(msg, sizeof(msg) - 1); \ return result; \ } \ result = new_result; \ - digit_multiply *= radix; \ + digit_multiply *= (_target_unsigned_type) radix; \ digits_count++; \ } \ if (digits_count < 1) { \ @@ -214,7 +228,7 @@ INT_TO_STR(u128, __uint128_t); return result; \ } \ if (neg) { \ - _target_unsigned_type result_first = result / 2; \ + _target_unsigned_type result_first = result >> (_target_unsigned_type) 1; \ _target_unsigned_type result_second = result - result_first; \ return - ((_target_type) result_first) - ((_target_type) result_second); \ } \ @@ -230,3 +244,14 @@ __uint128_t ir_builtin_str_to_u128(struct vector *arg_str) { COMMON_STR_TO_INTEGER(arg_str, __uint128_t, __uint128_t, false, 10) } + + +int256_t +ir_builtin_str_to_i256(struct vector *arg_str) { + COMMON_STR_TO_INTEGER(arg_str, int256_t, int256_t, true, 10); +} + +uint256_t +ir_builtin_str_to_u256(struct vector *arg_str) { + COMMON_STR_TO_INTEGER(arg_str, int256_t, int256_t, false, 10) +} \ No newline at end of file diff --git a/smart_ir/src/runtime/stdlib/math.h b/smart_ir/src/runtime/stdlib/math.h index a5fb4b0..ba9b6a4 100644 --- a/smart_ir/src/runtime/stdlib/math.h +++ b/smart_ir/src/runtime/stdlib/math.h @@ -17,6 +17,10 @@ extern "C" { #define uint128_t __uint128_t #define int128_t __int128_t +// int256 extension needs at least LLVM12 +typedef unsigned _ExtInt(256) uint256_t; +typedef _ExtInt(256) int256_t; + extern uint8_t ir_builtin_pow_u8(uint8_t base, uint8_t exp); @@ -28,6 +32,8 @@ extern uint64_t ir_builtin_pow_u64(uint64_t base, uint64_t exp); extern __uint128_t ir_builtin_pow_u128(__uint128_t base, __uint128_t exp); +extern uint256_t +ir_builtin_pow_u256(uint256_t base, uint256_t exp); extern int8_t ir_builtin_pow_i8(int8_t base, int8_t exp); @@ -39,6 +45,8 @@ extern int64_t ir_builtin_pow_i64(int64_t base, int64_t exp); extern __int128_t ir_builtin_pow_i128(__int128_t base, __int128_t exp); +extern int256_t +ir_builtin_pow_i256(int256_t base, int256_t exp); extern char * @@ -51,6 +59,8 @@ extern char * builtin_i64_toa(int64_t num, int radix); extern char * builtin_i128_toa(__int128_t num, int radix); +extern char * +builtin_i256_toa(int256_t num, int radix); extern char * builtin_u8_toa(uint8_t num, int radix); @@ -62,6 +72,8 @@ extern char * builtin_u64_toa(uint64_t num, int radix); extern char * builtin_u128_toa(__uint128_t num, int radix); +extern char * +builtin_u256_toa(uint256_t num, int radix); extern struct vector * ir_builtin_i8_to_str(int8_t num, int radix); @@ -73,6 +85,8 @@ extern struct vector * ir_builtin_i64_to_str(int64_t num, int radix); extern struct vector * ir_builtin_i128_to_str(__int128_t num, int radix); +extern struct vector * +ir_builtin_i256_to_str(int256_t num, int radix); extern struct vector * ir_builtin_u8_to_str(uint8_t num, int radix); @@ -84,10 +98,14 @@ extern struct vector * ir_builtin_u64_to_str(uint64_t num, int radix); extern struct vector * ir_builtin_u128_to_str(uint128_t num, int radix); +extern struct vector * +ir_builtin_u256_to_str(uint256_t num, int radix); // string to integer extern __int128_t ir_builtin_str_to_i128(struct vector *str); extern __uint128_t ir_builtin_str_to_u128(struct vector *str); +extern int256_t ir_builtin_str_to_i256(struct vector *str); +extern uint256_t ir_builtin_str_to_u256(struct vector *str); #ifdef __cplusplus } diff --git a/smart_ir/src/runtime/stdlib/qhashtbl.h b/smart_ir/src/runtime/stdlib/qhashtbl.h index 0bf9ee9..30ddb06 100644 --- a/smart_ir/src/runtime/stdlib/qhashtbl.h +++ b/smart_ir/src/runtime/stdlib/qhashtbl.h @@ -48,6 +48,12 @@ extern "C" { typedef struct qhashtbl_s qhashtbl_t; typedef struct qhashtbl_obj_s qhashtbl_obj_t; + +struct qhashtbl_iter { + struct qhashtbl_s* tbl; + struct qhashtbl_obj_s* obj; +}; + enum { QHASHTBL_THREADSAFE = (0x01) /*!< make it thread-safe */ }; diff --git a/smart_ir/src/runtime/stdlib/qstring.c b/smart_ir/src/runtime/stdlib/qstring.c index 3b7309e..eab0ed0 100644 --- a/smart_ir/src/runtime/stdlib/qstring.c +++ b/smart_ir/src/runtime/stdlib/qstring.c @@ -68,7 +68,7 @@ vector_to_bytes(struct vector *v) { uint32_t index = 0; // TODO: too slow and need too many gas when big str params to bytes while (index < v->len ) { - auto elem = v->data[index]; + int elem = v->data[index]; qvector_addlast(res, &elem); index ++; } diff --git a/smart_ir/src/runtime/stdlib/qstring.h b/smart_ir/src/runtime/stdlib/qstring.h index 6dfb45f..8922335 100644 --- a/smart_ir/src/runtime/stdlib/qstring.h +++ b/smart_ir/src/runtime/stdlib/qstring.h @@ -104,6 +104,10 @@ vector_insert(struct vector *v, struct vector *sub, int32_t index, qvector_t * vector_to_bytes(struct vector *v); +void +vector_appd(struct vector *v, uint8_t *bytes, uint32_t len, + struct RuntimeContext *ctx); + #ifdef __cplusplus } // end extern "C" #endif diff --git a/smart_ir/src/runtime/stdlib/qvector.c b/smart_ir/src/runtime/stdlib/qvector.c index 3a1eb06..172062e 100644 --- a/smart_ir/src/runtime/stdlib/qvector.c +++ b/smart_ir/src/runtime/stdlib/qvector.c @@ -80,6 +80,7 @@ #include "./stdlib.h" #include "./qinternal.h" #include "./qvector.h" +#include "./qstring.h" #ifndef _DOXGEN_SKIP diff --git a/smart_ir/src/runtime/stdlib/qvector.h b/smart_ir/src/runtime/stdlib/qvector.h index d5f8721..7032f63 100644 --- a/smart_ir/src/runtime/stdlib/qvector.h +++ b/smart_ir/src/runtime/stdlib/qvector.h @@ -50,6 +50,11 @@ extern "C" { typedef struct qvector_s qvector_t; typedef struct qvector_obj_s qvector_obj_t; +struct qvector_iter { + struct qvector_s* vec; + struct qvector_obj_s* obj; +}; + /* public functions */ enum { QVECTOR_THREADSAFE = (0x01), /*!< make it thread-safe */ diff --git a/smart_ir/src/runtime/stdlib/rlp.c b/smart_ir/src/runtime/stdlib/rlp.c index 7af4c30..c6af8d6 100644 --- a/smart_ir/src/runtime/stdlib/rlp.c +++ b/smart_ir/src/runtime/stdlib/rlp.c @@ -70,6 +70,30 @@ static size_t rlp_simple_encode_uint128_to_bytes(uint128_t value, uint8_t *buf) return bytes_count; } +static size_t rlp_simple_encode_uint256_to_bytes(uint256_t value, uint8_t *buf) { + if (value == (uint256_t) 0) { + return 0; // empty bytes means 0 + } + // the wasm is little endian, so just memcpy + const size_t max_bytes_size = sizeof(uint256_t); + uint8_t max_buf[max_bytes_size]; + uint256_t *value_mem = (uint256_t*) __malloc(sizeof(uint256_t)); + *value_mem = value; + memcpy(max_buf, value_mem, sizeof(uint256_t)); + size_t bytes_count = max_bytes_size; // at least 1 + for (int32_t i=max_bytes_size-1;i>0;i--) { // at least need one byte + if (max_buf[i] != 0) { + break; + } + bytes_count--; + } + // buf is reverse of max_buf, but only contains needed data + for (size_t i=0;i=0;i--) { // i must be int32_t, otherwise loop forever + sum +=(uint256_t) multiply * (uint256_t) buf[i]; + if (i >= 1) { + multiply *= (uint256_t)256; // 1 << 8 + } + } + return sum; +} + static inline void __attribute__((artificial)) __attribute__((always_inline)) rlp_encode_length(ByteStream *stream, size_t len, size_t offset) { @@ -317,6 +353,14 @@ void common_rlp_encode(ByteStream *stream, uint32_t runtime_class_offset, void * rlp_encode_bytes(stream, bytes); } break; + case IR_RUNTIME_TYPE_U256: { + uint256_t ival = *((uint256_t *) val); + qvector_t *bytes = qvector(sizeof(uint256_t), 1, QVECTOR_RESIZE_DOUBLE); + int32_t n = rlp_simple_encode_uint256_to_bytes(ival, bytes->data); + bytes->num = n; + rlp_encode_bytes(stream, bytes); + } + break; case IR_RUNTIME_TYPE_I8: { int8_t ival = *((int8_t *) val); qvector_t *bytes = qvector(8, 1, QVECTOR_RESIZE_DOUBLE); @@ -362,6 +406,15 @@ void common_rlp_encode(ByteStream *stream, uint32_t runtime_class_offset, void * rlp_encode_bytes(stream, bytes); } break; + case IR_RUNTIME_TYPE_I256: { + int256_t ival = *((int256_t *) val); + qvector_t *bytes = qvector(sizeof(int256_t), 1, QVECTOR_RESIZE_DOUBLE); + // TODO: use uint256 + int32_t n = rlp_simple_encode_uint256_to_bytes(ival, bytes->data); + bytes->num = n; + rlp_encode_bytes(stream, bytes); + } + break; case IR_RUNTIME_TYPE_BOOL: { bool bool_val = *((bool *) val); uint8_t ival = bool_val ? 1 : 0; @@ -493,6 +546,13 @@ void *common_rlp_decode(ByteStream *stream, uint32_t runtime_class_offset) { *value = rlp_simple_decode_uint128(int_bytes->data, int_bytes->num); return value; } break; + case IR_RUNTIME_TYPE_U256: + { + qvector_t *int_bytes = rlp_decode(stream); + uint256_t *value = (uint256_t *) __malloc(sizeof(uint256_t)); + *value = rlp_simple_decode_uint256(int_bytes->data, int_bytes->num); + return value; + } break; case IR_RUNTIME_TYPE_I8: { qvector_t *int_bytes = rlp_decode(stream); int32_t value = rlp_simple_decode_uint64(int_bytes->data, int_bytes->num); @@ -528,6 +588,13 @@ void *common_rlp_decode(ByteStream *stream, uint32_t runtime_class_offset) { *value = rlp_simple_decode_uint128(int_bytes->data, int_bytes->num); return value; } break; + case IR_RUNTIME_TYPE_I256: + { + qvector_t *int_bytes = rlp_decode(stream); + int256_t *value = (int256_t *) __malloc(sizeof(int256_t)); + *value = rlp_simple_decode_uint256(int_bytes->data, int_bytes->num); + return value; + } break; case IR_RUNTIME_TYPE_BOOL: { qvector_t *int_bytes = rlp_decode(stream); diff --git a/smart_ir/src/runtime/stdlib/ssz.c b/smart_ir/src/runtime/stdlib/ssz.c index 167001c..be2b971 100644 --- a/smart_ir/src/runtime/stdlib/ssz.c +++ b/smart_ir/src/runtime/stdlib/ssz.c @@ -56,11 +56,13 @@ SSZ_ENCODE_INT_DECLARE(u16, uint16_t) SSZ_ENCODE_INT_DECLARE(u32, uint32_t) SSZ_ENCODE_INT_DECLARE(u64, uint64_t) SSZ_ENCODE_INT_DECLARE(u128, uint128_t) +SSZ_ENCODE_INT_DECLARE(u256, uint256_t) SSZ_ENCODE_INT_DECLARE(i8, int8_t) SSZ_ENCODE_INT_DECLARE(i16, int16_t) SSZ_ENCODE_INT_DECLARE(i32, int32_t) SSZ_ENCODE_INT_DECLARE(i64, int64_t) SSZ_ENCODE_INT_DECLARE(i128, int128_t) +SSZ_ENCODE_INT_DECLARE(i256, int256_t) SSZ_DECODE_INT_DECLARE(bool, uint8_t) SSZ_DECODE_INT_DECLARE(u8, uint8_t) @@ -68,11 +70,13 @@ SSZ_DECODE_INT_DECLARE(u16, uint16_t) SSZ_DECODE_INT_DECLARE(u32, uint32_t) SSZ_DECODE_INT_DECLARE(u64, uint64_t) SSZ_DECODE_INT_DECLARE(u128, uint128_t) +SSZ_DECODE_INT_DECLARE(u256, uint256_t) SSZ_DECODE_INT_DECLARE(i8, int8_t) SSZ_DECODE_INT_DECLARE(i16, int16_t) SSZ_DECODE_INT_DECLARE(i32, int32_t) SSZ_DECODE_INT_DECLARE(i64, int64_t) SSZ_DECODE_INT_DECLARE(i128, int128_t) +SSZ_DECODE_INT_DECLARE(i256, int256_t) int32_t ssz_encode_str(const struct vector *v, uint8_t *buf, int32_t hdr_offset, @@ -147,12 +151,14 @@ IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(u16, uint16_t, 2) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(u32, uint32_t, 4) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(u64, uint64_t, 8) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(u128, uint128_t, 16) +IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(u256, uint256_t, 32) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i8, int8_t, 1) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i16, int16_t, 2) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i32, int32_t, 4) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i64, int64_t, 8) IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i128, int128_t, 16) +IR_BUILTIN_SSZ_ENCODE_INT_DECLARE(i256, int256_t, 32) #define IR_BUILTIN_SSZ_DECODE_INT_DECLARE(id, ty, size) \ void *ir_builtin_ssz_decode_##id(qvector_t *val) \ @@ -168,12 +174,14 @@ IR_BUILTIN_SSZ_DECODE_INT_DECLARE(u16, uint16_t, 2) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(u32, uint32_t, 4) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(u64, uint64_t, 8) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(u128, uint128_t, 16) +IR_BUILTIN_SSZ_DECODE_INT_DECLARE(u256, uint256_t, 32) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i8, int8_t, 1) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i16, int16_t, 2) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i32, int32_t, 4) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i64, int64_t, 8) IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i128, int128_t, 16) +IR_BUILTIN_SSZ_DECODE_INT_DECLARE(i256, int256_t, 32) // When this type is encoded to [u8], whether the length of the array is fixed bool @@ -204,6 +212,10 @@ is_ssz_fixed_len(uint32_t runtime_class_offset) { return true; } break; + case IR_RUNTIME_TYPE_U256: + { + return true; + } break; case IR_RUNTIME_TYPE_I8: { return true; @@ -224,6 +236,10 @@ is_ssz_fixed_len(uint32_t runtime_class_offset) { return true; } break; + case IR_RUNTIME_TYPE_I256: + { + return true; + } break; case IR_RUNTIME_TYPE_BOOL: { return true; @@ -306,6 +322,10 @@ ssz_encode_len(uint32_t runtime_class_offset, void *val) { return 16; } break; + case IR_RUNTIME_TYPE_U256: + { + return 32; + } break; case IR_RUNTIME_TYPE_I8: { return 1; @@ -326,6 +346,10 @@ ssz_encode_len(uint32_t runtime_class_offset, void *val) { return 16; } break; + case IR_RUNTIME_TYPE_I256: + { + return 32; + } break; case IR_RUNTIME_TYPE_BOOL: { return 1; @@ -453,6 +477,10 @@ ssz_fix_ty_length(uint32_t runtime_class_offset) { return 16; } break; + case IR_RUNTIME_TYPE_U256: + { + return 32; + } break; case IR_RUNTIME_TYPE_I8: { return 1; @@ -473,6 +501,10 @@ ssz_fix_ty_length(uint32_t runtime_class_offset) { return 16; } break; + case IR_RUNTIME_TYPE_I256: + { + return 32; + } break; case IR_RUNTIME_TYPE_BOOL: { return 1; @@ -962,6 +994,10 @@ ir_builtin_ssz_encode(uint32_t runtime_class_offset, void *val) { return ir_builtin_ssz_encode_u128(val); } break; + case IR_RUNTIME_TYPE_U256: + { + return ir_builtin_ssz_encode_u256(val); + } break; case IR_RUNTIME_TYPE_I8: { return ir_builtin_ssz_encode_i8(val); @@ -982,6 +1018,10 @@ ir_builtin_ssz_encode(uint32_t runtime_class_offset, void *val) { return ir_builtin_ssz_encode_i128(val); } break; + case IR_RUNTIME_TYPE_I256: + { + return ir_builtin_ssz_encode_i256(val); + } break; case IR_RUNTIME_TYPE_BOOL: { return ir_builtin_ssz_encode_bool(val); @@ -1073,6 +1113,10 @@ ir_builtin_ssz_decode_impl(uint32_t runtime_class_offset, { return ir_builtin_ssz_decode_u128(val); } break; + case IR_RUNTIME_TYPE_U256: + { + return ir_builtin_ssz_decode_u256(val); + } break; case IR_RUNTIME_TYPE_I8: { return ir_builtin_ssz_decode_i8(val); @@ -1093,6 +1137,10 @@ ir_builtin_ssz_decode_impl(uint32_t runtime_class_offset, { return ir_builtin_ssz_decode_i128(val); } break; + case IR_RUNTIME_TYPE_I256: + { + return ir_builtin_ssz_decode_i256(val); + } break; case IR_RUNTIME_TYPE_BOOL: { return ir_builtin_ssz_decode_bool(val); diff --git a/smart_ir/src/runtime/stdlib/ssz.h b/smart_ir/src/runtime/stdlib/ssz.h index 4b80acb..358e56c 100644 --- a/smart_ir/src/runtime/stdlib/ssz.h +++ b/smart_ir/src/runtime/stdlib/ssz.h @@ -51,6 +51,11 @@ ssz_encode_u128(uint128_t v, uint8_t *buf, int32_t offset); extern int32_t ssz_decode_u128(uint128_t *v, uint8_t *buf); +extern int32_t +ssz_encode_u256(uint256_t v, uint8_t *buf, int32_t offset); +extern int32_t +ssz_decode_u256(uint256_t *v, uint8_t *buf); + extern int32_t ssz_encode_i8(int8_t v, uint8_t *buf, int32_t offset); extern int32_t @@ -76,6 +81,11 @@ ssz_encode_i128(int128_t v, uint8_t *buf, int32_t offset); extern int32_t ssz_decode_i128(int128_t *v, uint8_t *buf); +extern int32_t +ssz_encode_i256(int256_t v, uint8_t *buf, int32_t offset); +extern int32_t +ssz_decode_i256(int256_t *v, uint8_t *buf); + extern int32_t ssz_encode_str(const struct vector *v, uint8_t *buf, int32_t hdr_offset, int32_t data_offset); diff --git a/smart_ir/src/runtime/stdlib/stdlib.c b/smart_ir/src/runtime/stdlib/stdlib.c index 7ed6fba..ef5f350 100644 --- a/smart_ir/src/runtime/stdlib/stdlib.c +++ b/smart_ir/src/runtime/stdlib/stdlib.c @@ -58,6 +58,10 @@ extern int32_t get_call_result_length(void); // get_call_result hostapi extern void get_call_result(char *result); +uint256_t div256_u256_rem(uint256_t dividend, uint256_t divisor, uint256_t *remainder); + +uint256_t div256_u256(uint256_t dividend, uint256_t divisor); + void runtime_abort(char *msg, uint32_t msg_length, struct RuntimeContext *runtime_context) @@ -472,35 +476,35 @@ memcpy_offset(uint8_t *des, int32_t des_length, int32_t offset, uint8_t *src, } size_t -__numlen(int128_t num) +__numlen(int256_t num) { - if (num == 0) { + if (num == (int256_t) 0) { return 1; } int32_t flag = 0; int32_t len = 0; - if (num == INT128_MIN) { - num = (int128_t)num + 1; + if (num == INT256_MIN) { + num = num + (int256_t)1; } - if (num < 0) { + if (num < (int256_t)0) { num = -num; flag = 1; } - for(; num > 0; ++len) { - num /= 10; + for(; num >(int256_t) 0; ++len) { + num = div256_u256(num, (int256_t) 10); } return len + flag; } size_t -__unumlen(uint128_t num) +__unumlen(uint256_t num) { - if (num == 0) { + if (num == (uint256_t)0) { return 1; } int32_t len = 0; - for(; num > 0; ++len) { - num /= 10; + for(; num >(uint256_t) 0; ++len) { + num = div256_u256(num, (uint256_t) 10); } return len; } @@ -581,14 +585,15 @@ __isalpha(int32_t c) return ((unsigned)c|32)-'a' < 26; } -int128_t __strtoi128(const char *__restrict nptr, +int256_t __strtoi256(const char *__restrict nptr, char **__restrict endptr, int base) { register const unsigned char *s = (const unsigned char *) nptr; - register uint128_t acc; + register uint256_t acc; register int c; - register uint128_t cutoff; - register int neg = 0, any, cutlim; + register uint256_t cutoff; + register int neg = 0, any; + uint256_t cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else @@ -627,9 +632,9 @@ int128_t __strtoi128(const char *__restrict nptr, * Set any if any `digits' consumed; make it negative to indicate * overflow. */ - cutoff = neg ? -(uint128_t) INT128_MIN : INT128_MAX; - cutlim = cutoff % (uint128_t) base; - cutoff /= (uint128_t) base; + cutoff = neg ? -(int256_t) INT256_MIN : INT256_MAX; + + cutoff = div256_u256_rem((uint256_t) cutoff, (uint256_t) base, &cutlim); for (acc = 0, any = 0;; c = *s++) { if (__isdigit(c)) c -= '0'; @@ -643,12 +648,12 @@ int128_t __strtoi128(const char *__restrict nptr, any = -1; else { any = 1; - acc *= base; - acc += c; + acc *= (uint256_t)base; + acc += (uint256_t)c; } } if (any < 0) { - acc = neg ? INT128_MIN : INT128_MAX; + acc = neg ? INT256_MIN : INT256_MAX; } else if (neg) acc = -acc; if (endptr != 0) @@ -657,15 +662,16 @@ int128_t __strtoi128(const char *__restrict nptr, } -uint128_t __strtou128(const char *__restrict nptr, +uint256_t __strtou256(const char *__restrict nptr, char **__restrict endptr, int base) { register const unsigned char *s = (const unsigned char *)nptr; - register uint128_t acc; + register uint256_t acc; register int c; - register uint128_t cutoff; - register int neg = 0, any, cutlim; + register uint256_t cutoff; + register int neg = 0, any; + uint256_t cutlim; /* * See strtol for comments as to the logic used. */ @@ -685,8 +691,7 @@ uint128_t __strtou128(const char *__restrict nptr, } if (base == 0) base = c == '0' ? 8 : 10; - cutoff = (uint128_t)UINT128_MAX / (uint128_t)base; - cutlim = (uint128_t)UINT128_MAX % (uint128_t)base; + cutoff = div256_u256_rem(UINT256_MAX, (uint256_t) base, &cutlim); for (acc = 0, any = 0;; c = *s++) { if (__isdigit(c)) c -= '0'; @@ -700,12 +705,12 @@ uint128_t __strtou128(const char *__restrict nptr, any = -1; else { any = 1; - acc *= base; - acc += c; + acc *= (uint256_t)base; + acc += (uint256_t)c; } } if (any < 0) { - acc = UINT128_MAX; + acc = UINT256_MAX; } else if (neg) acc = -acc; if (endptr != 0) @@ -740,3 +745,73 @@ void builtin_co_call_or_revert(const char *contract, } } } + + + +int __fls(uint128_t value ) { + return value - (value & (value - 1)); +} + +uint256_t div256_128(uint256_t n, uint128_t base, uint128_t *rem) +{ + uint256_t rem_256 = n ; + uint256_t b = (uint256_t) base; + uint256_t res, d = 1; + uint128_t high = (uint128_t) (n >> (uint256_t) 128); + + res = 0; + if (high >= base) { + high /= base; + res = (uint256_t) high << (uint256_t) 128; + rem_256 -= ((uint256_t)high* (uint256_t)base) << (uint256_t) 128; + } + + while (b >(uint256_t) 0 && b < rem_256) { + b = b+b; + d = d+d; + } + + do { + if (rem_256 >= b) { + rem_256 -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *rem = (uint128_t) rem_256; + return res; +} + + +uint256_t div256_u256_rem(uint256_t dividend, uint256_t divisor, uint256_t *remainder) +{ + uint128_t high = (uint128_t) (divisor >>(uint256_t) 128); + uint256_t quot; + + if (high == 0) { + uint128_t rem128; + quot = div256_128(dividend, (uint128_t) divisor, &rem128); + *remainder = (uint256_t) rem128; + } else { + uint128_t rem128; + int n = __fls(high); + quot = div256_128(dividend >> n, divisor >> n,&rem128); + + if (quot != 0) + quot--; + + *remainder = dividend - quot * divisor; + if (*remainder >= divisor) { + quot++; + *remainder -= divisor; + } + } + + return quot; +} + +uint256_t div256_u256(uint256_t dividend, uint256_t divisor) { + uint256_t rem; + return div256_u256_rem(dividend, divisor, &rem); +} \ No newline at end of file diff --git a/smart_ir/src/runtime/stdlib/stdlib.h b/smart_ir/src/runtime/stdlib/stdlib.h index 819a5db..138a59d 100644 --- a/smart_ir/src/runtime/stdlib/stdlib.h +++ b/smart_ir/src/runtime/stdlib/stdlib.h @@ -18,10 +18,19 @@ #define uint128_t __uint128_t #define int128_t __int128_t + +// int256 extension needs at least LLVM12 +typedef unsigned _ExtInt(256) uint256_t; +typedef _ExtInt(256) int256_t; + #define INT128_MAX (__int128) (((unsigned __int128) 1 << ((__SIZEOF_INT128__ * __CHAR_BIT__) - 1)) - 1) #define INT128_MIN ((__int128_t)0 - ((__int128_t)1 << 126) - ((__int128_t)1 << 126)) #define UINT128_MAX (((__uint128_t)INT128_MAX << 1) + 1) +#define INT256_MAX (int256_t) (((uint256_t) 1 << (uint256_t)((2 * __SIZEOF_INT128__ * __CHAR_BIT__) - 1)) - (uint256_t)1) +#define INT256_MIN ((int256_t)0 - ((int256_t)1 << (int256_t)126) - ((int256_t)1 << (int256_t)126)) +#define UINT256_MAX (((uint256_t)INT256_MAX << (uint256_t)1) + (uint256_t)1) + /* * Vector is used for dynamic array */ @@ -75,15 +84,20 @@ __tolower(int32_t c); char * __strcpy(char *__restrict dest, const char *__restrict src); size_t -__numlen(int128_t num); +__numlen(int256_t num); size_t -__unumlen(uint128_t num); +__unumlen(uint256_t num); int32_t __strncmp(const char *_l, const char *_r, size_t n); -int128_t -__strtoi128(const char *__restrict nptr, char **__restrict endptr, int base); -uint128_t -__strtou128(const char *__restrict nptr, char **__restrict endptr, int base); +int256_t +__strtoi256(const char *__restrict nptr, char **__restrict endptr, int base); +uint256_t +__strtou256(const char *__restrict nptr, char **__restrict endptr, int base); + +//bigint div +uint256_t div256_u256_rem(uint256_t dividend, uint256_t divisor, uint256_t *remainder); + +uint256_t div256_u256(uint256_t dividend, uint256_t divisor); #define malloc __malloc diff --git a/smart_ir/src/runtime/stdlib/wasmheap.c b/smart_ir/src/runtime/stdlib/wasmheap.c index 9a34d10..42c42c7 100644 --- a/smart_ir/src/runtime/stdlib/wasmheap.c +++ b/smart_ir/src/runtime/stdlib/wasmheap.c @@ -121,8 +121,8 @@ __init_heap() // disable re-call abi using the same vm(memory not free) return; } - heap_ptr = __builtin_wasm_memory_grow(0, 0) * WASM_PAGE_SIZE; - heap_top = __builtin_wasm_memory_grow(0, 1) * WASM_PAGE_SIZE; + //heap_ptr = __builtin_wasm_memory_grow(0, 0) * WASM_PAGE_SIZE; + //heap_top = __builtin_wasm_memory_grow(0, 1) * WASM_PAGE_SIZE; init_free(); void* tmp = __malloc(1); // malloc 1 byte to let memory grow to available size @@ -192,9 +192,9 @@ ____malloc_new_allocation(size_t size) if (heap_ptr >= heap_top) { unsigned int pages = (block_size / WASM_PAGE_SIZE) + 1; - if (__builtin_wasm_memory_grow(0, pages) == -1) { - __abort("__malloc: failed"); - }; + // if (__builtin_wasm_memory_grow(0, pages) == -1) { + // __abort("__malloc: failed"); + //}; heap_top += (pages * WASM_PAGE_SIZE); }