Pārlūkot izejas kodu

LLVM 15 (#1165)

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>
Lucas Steuernagel 2 gadi atpakaļ
vecāks
revīzija
4bb4747da0

+ 0 - 42
.github/Dockerfile

@@ -1,42 +0,0 @@
-FROM ubuntu:20.04 as builder
-
-LABEL org.opencontainers.image.licenses="Apache-2.0" \
-    org.opencontainers.image.description="CI container for Hyperledger Solang github actions"
-
-ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update -y
-RUN apt-get upgrade -y
-RUN apt-get install -y libz-dev pkg-config libssl-dev git cmake ninja-build gcc g++ python3
-
-RUN git clone --single-branch --branch solana-rustc/14.0-2022-03-22 \
-    https://github.com/solana-labs/llvm-project.git
-
-WORKDIR /llvm-project
-
-RUN cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off \
-    -DLLVM_ENABLE_PROJECTS=clang\;lld \
-    -DLLVM_TARGETS_TO_BUILD=WebAssembly\;BPF \
-    -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=/llvm14.0 llvm
-
-RUN cmake --build . --target install
-
-FROM ubuntu:20.04
-
-ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update
-RUN apt-get install -y zlib1g-dev pkg-config libssl-dev git libffi-dev curl gcc g++ make python3
-RUN apt-get clean
-RUN apt-get autoclean
-
-# Get Rust
-RUN curl https://sh.rustup.rs -sSf | bash -s -- -y --default-toolchain 1.64.0
-
-COPY --from=builder /llvm14.0 /llvm14.0/
-
-ENV PATH="/llvm14.0/bin:/root/.cargo/bin:/root/.local/share/solana/install/active_release/bin:${PATH}"
-
-# Install Solana (x86-64 only, does not work on arm)
-RUN if test `arch` = x86_64; then sh -c "$(curl -sSfL https://release.solana.com/v1.11.10/install)"; fi
-
-# Install Anchor tools
-RUN cargo install --git https://github.com/coral-xyz/anchor --tag v0.25.0 anchor-cli

+ 0 - 165
.github/workflows/build-llvm.yml

@@ -1,165 +0,0 @@
-name: Build LLVM Libraries
-on: [workflow_dispatch]
-jobs:
-  create:
-    name: Create Release
-    runs-on: ubuntu-latest
-    outputs:
-      upload_url: ${{ steps.create_release.outputs.upload_url }}
-    steps:
-    - name: Create Release
-      id: create_release
-      uses: actions/create-release@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        tag_name: llvm14.0-1
-        release_name: LLVM Libraries v14.0 (v1)
-        draft: false
-        prerelease: false
-
-  linux-x86-64:
-    name: Linux x86-64
-    runs-on: ubuntu-20.04
-    needs: create
-    steps:
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-linux-x86-64.tar.xz ./llvm14.0/
-    - name: Upload Release Asset
-      id: upload-release-asset
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ needs.create.outputs.upload_url }}
-        asset_path: ./llvm14.0-linux-x86-64.tar.xz
-        asset_name: llvm14.0-linux-x86-64.tar.xz
-        asset_content_type: application/x-xz
-
-  linux-arm64:
-    name: Linux arm64
-    runs-on: linux-arm64
-    if: ${{ github.repository_owner == 'hyperledger' }}
-    needs: create
-    steps:
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-linux-arm64.tar.xz ./llvm14.0/
-    - name: Upload Release Asset
-      id: upload-release-asset
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ needs.create.outputs.upload_url }}
-        asset_path: ./llvm14.0-linux-arm64.tar.xz
-        asset_name: llvm14.0-linux-arm64.tar.xz
-        asset_content_type: application/x-xz
-
-  mac-arm:
-    name: Mac Arm
-    needs: create
-    runs-on: [self-hosted, macOS, ARM64, MacStadium]
-    if: ${{ github.repository_owner == 'hyperledger' }}
-    steps:
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-#    - name: Install Ninja
-#      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-mac-arm.tar.xz ./llvm14.0/
-    - name: Upload Release Asset
-      id: upload-release-asset
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ needs.create.outputs.upload_url }}
-        asset_path: ./llvm14.0-mac-arm.tar.xz
-        asset_name: llvm14.0-mac-arm.tar.xz
-        asset_content_type: application/x-xz
-
-  mac-intel:
-    name: Mac Intel
-    needs: create
-    runs-on: macos-11
-    steps:
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-mac-intel.tar.xz ./llvm14.0/
-    - name: Upload Release Asset
-      id: upload-release-asset
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ needs.create.outputs.upload_url }}
-        asset_path: ./llvm14.0-mac-intel.tar.xz
-        asset_name: llvm14.0-mac-intel.tar.xz
-        asset_content_type: application/x-xz
-
-  windows:
-    name: Windows
-    needs: create
-    runs-on: windows-latest
-    steps:
-    - run: Get-Volume
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-      # We may not have enough space to compile llvm, see https://github.com/actions/virtual-environments/issues/326
-      working-directory: C:\
-    - name: Setup Windows
-      uses: llvm/actions/setup-windows@main
-      with:
-        arch: amd64
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        '-DLLVM_ENABLE_PROJECTS=clang;lld'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=C:/llvm14.0 llvm
-      working-directory: C:\llvm-project
-    - run: cmake --build . --target install
-      working-directory: C:\llvm-project
-    - run: Compress-Archive -Path C:\llvm14.0 -DestinationPath C:\llvm14.0-win.zip
-    - name: Upload Release Asset
-      id: upload-release-asset
-      uses: actions/upload-release-asset@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      with:
-        upload_url: ${{ needs.create.outputs.upload_url }}
-        asset_path: C:\llvm14.0-win.zip
-        asset_name: llvm14.0-win.zip
-        asset_content_type: application/zip

+ 0 - 11
.github/workflows/ci-image.yml

@@ -1,11 +0,0 @@
-name: Build and push ci image
-on: [workflow_dispatch]
-jobs:
-  build-push-ci-image:
-    runs-on: linux-arm64
-    steps:
-    - name: Checkout sources
-      uses: actions/checkout@v1
-    - run: |
-          echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
-          docker buildx build --provenance=false --platform linux/amd64,linux/arm64 -t ghcr.io/${GITHUB_REPOSITORY}:ci --push .github

+ 20 - 106
.github/workflows/release.yml

@@ -9,32 +9,12 @@ jobs:
   linux-x86-64:
     name: Linux x86-64
     runs-on: ubuntu-20.04
+    container: ghcr.io/hyperledger/solang-llvm:ci
     steps:
     - name: Checkout sources
       uses: actions/checkout@v2
       with:
         submodules: recursive
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-linux-x86-64.tar.xz ./llvm14.0/
-    - name: Upload llvm
-      uses: svenstaro/upload-release-action@v2
-      with:
-        repo_token: ${{ secrets.GITHUB_TOKEN }}
-        file: llvm14.0-linux-x86-64.tar.xz
-        asset_name: llvm14.0-linux-x86-64.tar.xz
-        tag: ${{ github.ref }}
-    - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
     - name: Rust stable
       run: rustup default 1.64.0
     - name: Build
@@ -53,30 +33,12 @@ jobs:
     name: Linux arm64
     runs-on: linux-arm64
     if: ${{ github.repository_owner == 'hyperledger' }}
+    container: ghcr.io/hyperledger/solang-llvm:ci
     steps:
     - name: Checkout sources
       uses: actions/checkout@v2
       with:
         submodules: recursive
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-linux-arm64.tar.xz ./llvm14.0/
-    - name: Upload llvm
-      uses: svenstaro/upload-release-action@v2
-      with:
-        repo_token: ${{ secrets.GITHUB_TOKEN }}
-        file: llvm14.0-linux-arm64.tar.xz
-        asset_name: llvm14.0-linux-arm64.tar.xz
-        tag: ${{ github.ref }}
-    - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
     - name: Rust stable
       run: rustup default 1.64.0
     - name: Build
@@ -96,36 +58,18 @@ jobs:
     runs-on: windows-latest
     steps:
     - name: Checkout sources
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
       with:
         submodules: recursive
+    - name: Download LLVM
+      run: curl -sSL -o c:\llvm.zip https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-win.zip
+    - name: Extract LLVM
+      run: unzip c:\llvm.zip -d c:/
+    - name: Add LLVM to Path
+      run: echo "c:\llvm15.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
     - uses: dtolnay/rust-toolchain@1.64.0
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-      # We may not have enough space to compile llvm, see https://github.com/actions/virtual-environments/issues/326
-      working-directory: C:\
-    - name: Setup Windows
-      uses: llvm/actions/setup-windows@main
       with:
-        arch: amd64
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        '-DLLVM_ENABLE_PROJECTS=clang;lld'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=C:/llvm14.0 llvm
-      working-directory: C:\llvm-project
-    - run: cmake --build . --target install
-      working-directory: C:\llvm-project
-    - run: Compress-Archive -Path C:\llvm14.0 -DestinationPath C:\llvm14.0-win.zip
-    - name: Upload llvm
-      uses: svenstaro/upload-release-action@v2
-      with:
-        repo_token: ${{ secrets.GITHUB_TOKEN }}
-        file: C:\llvm14.0-win.zip
-        asset_name: llvm14.0-win.zip
-        tag: ${{ github.ref }}
-    - name: Add LLVM to Path
-      run: echo "c:\llvm14.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
+        components: clippy
     - name: Build
       run: cargo build --release --verbose
     - name: Run tests
@@ -148,27 +92,12 @@ jobs:
       with:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@1.64.0
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-mac-arm.tar.xz ./llvm14.0/
-    - name: Upload llvm
-      uses: svenstaro/upload-release-action@v2
-      with:
-        repo_token: ${{ secrets.GITHUB_TOKEN }}
-        file: llvm14.0-mac-arm.tar.xz
-        asset_name: llvm14.0-mac-arm.tar.xz
-        tag: ${{ github.ref }}
+    - name: Get LLVM
+      run: curl -L --output llvm15.0-mac-arm.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-arm.tar.xz
+    - name: Extract LLVM
+      run: tar Jxf llvm15.0-mac-arm.tar.xz
     - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
+      run: echo "$(pwd)/llvm15.0/bin" >> $GITHUB_PATH
     - name: Build
       run: cargo build --release --verbose
     - name: Run tests
@@ -193,27 +122,12 @@ jobs:
       with:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@1.64.0
-    - run: git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project.git
-    - name: Install Ninja
-      uses: llvm/actions/install-ninja@main
-    - run: cmake -G Ninja -DLLVM_ENABLE_ASSERTIONS=On -DLLVM_ENABLE_TERMINFO=Off
-        -DLLVM_ENABLE_LIBXML2=Off -DLLVM_ENABLE_ZLIB=Off
-        -DLLVM_ENABLE_PROJECTS='clang;lld'
-        -DLLVM_TARGETS_TO_BUILD='WebAssembly;BPF'
-        -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=../llvm14.0 llvm
-      working-directory: ./llvm-project/
-    - run: cmake --build . --target install
-      working-directory: ./llvm-project/
-    - run: tar Jcf ./llvm14.0-mac-intel.tar.xz ./llvm14.0/
-    - name: Upload llvm
-      uses: svenstaro/upload-release-action@v2
-      with:
-        repo_token: ${{ secrets.GITHUB_TOKEN }}
-        file: llvm14.0-mac-intel.tar.xz
-        asset_name: llvm14.0-mac-intel.tar.xz
-        tag: ${{ github.ref }}
+    - name: Get LLVM
+      run: wget -q -O llvm15.0-mac-intel.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-intel.tar.xz
+    - name: Extract LLVM
+      run: tar Jxf llvm15.0-mac-intel.tar.xz
     - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
+      run: echo "$(pwd)/llvm15.0/bin" >> $GITHUB_PATH
     - name: Build
       run: cargo build --release --verbose
     - name: Run tests

+ 13 - 13
.github/workflows/test.yml

@@ -19,7 +19,7 @@ jobs:
   lints:
     name: Lints
     runs-on: ubuntu-20.04
-    container: ghcr.io/hyperledger/solang:ci
+    container: ghcr.io/hyperledger/solang-llvm:ci
     steps:
       - name: Checkout sources
         uses: actions/checkout@v3
@@ -59,7 +59,7 @@ jobs:
   linux-x86-64:
     name: Linux x86-64
     runs-on: ubuntu-20.04
-    container: ghcr.io/hyperledger/solang:ci
+    container: ghcr.io/hyperledger/solang-llvm:ci
     steps:
     - name: Checkout sources
       uses: actions/checkout@v3
@@ -80,7 +80,7 @@ jobs:
     name: Linux Arm
     runs-on: linux-arm64
     if: ${{ github.repository_owner == 'hyperledger' }}
-    container: ghcr.io/hyperledger/solang:ci
+    container: ghcr.io/hyperledger/solang-llvm:ci
     steps:
     - name: Checkout sources
       uses: actions/checkout@v3
@@ -106,11 +106,11 @@ jobs:
       with:
         submodules: recursive
     - name: Download LLVM
-      run: curl -sSL -o c:\llvm.zip https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-win.zip
+      run: curl -sSL -o c:\llvm.zip https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-win.zip
     - name: Extract LLVM
       run: unzip c:\llvm.zip -d c:/
     - name: Add LLVM to Path
-      run: echo "c:\llvm14.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
+      run: echo "c:\llvm15.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
     - uses: dtolnay/rust-toolchain@1.64.0
       with:
         components: clippy
@@ -137,11 +137,11 @@ jobs:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@1.64.0
     - name: Get LLVM
-      run: curl -L --output llvm14.0-mac-arm.tar.xz https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-mac-arm.tar.xz
+      run: curl -L --output llvm15.0-mac-arm.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-arm.tar.xz
     - name: Extract LLVM
-      run: tar Jxf llvm14.0-mac-arm.tar.xz
+      run: tar Jxf llvm15.0-mac-arm.tar.xz
     - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
+      run: echo "$(pwd)/llvm15.0/bin" >> $GITHUB_PATH
     - name: Build
       run: cargo build --verbose
     - name: Run tests
@@ -161,11 +161,11 @@ jobs:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@1.64.0
     - name: Get LLVM
-      run: wget -q -O llvm14.0-mac-intel.tar.xz https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-mac-intel.tar.xz
+      run: wget -q -O llvm15.0-mac-intel.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-intel.tar.xz
     - name: Extract LLVM
-      run: tar Jxf llvm14.0-mac-intel.tar.xz
+      run: tar Jxf llvm15.0-mac-intel.tar.xz
     - name: Add LLVM to Path
-      run: echo "$(pwd)/llvm14.0/bin" >> $GITHUB_PATH
+      run: echo "$(pwd)/llvm15.0/bin" >> $GITHUB_PATH
     - name: Build
       run: cargo build --verbose
     - name: Run tests
@@ -216,7 +216,7 @@ jobs:
   anchor:
     name: Anchor Integration test
     runs-on: ubuntu-latest
-    container: ghcr.io/hyperledger/solang:ci
+    container: ghcr.io/hyperledger/solang-llvm:ci
     needs: linux-x86-64
     steps:
     - name: Checkout sources
@@ -260,7 +260,7 @@ jobs:
   solana:
     name: Solana Integration test
     runs-on: ubuntu-latest
-    container: ghcr.io/hyperledger/solang:ci
+    container: ghcr.io/hyperledger/solang-llvm:ci
     needs: linux-x86-64
     steps:
     - name: Checkout sources

+ 19 - 0
CHANGELOG.md

@@ -2,6 +2,25 @@
 All notable changes to [Solang](https://github.com/hyperledger/solang/)
 will be documented here.
 
+## v0.2.2 (unreleased)
+
+### Added
+- Solidity mappings can now have named key and named value types. [seanyoung](https://github.com/seanyoung)
+
+### Changed
+- Solang now uses LLVM 15. [LucasSte](https://github.com/LucasSte)
+- Solidity on Solana now required the Anchor framework for the client code, and the `@solana/solidity.js`
+  Typescript library is no longer compatible with Solidity.
+- When casting hex literal numbers into the `bytesN` type, the hex literal may use leading zeros to match the size 
+with the according `bytesN`, which aligns solang with `solc`. [xermicus](https://github.com/xermicus)
+
+### Fixed
+- Many bugs have been fixed by [seanyoung](https://github.com/seanyoung), [LucasSte](https://github.com/LucasSte)
+  and [xermicus](https://github.com/xermicus)
+- Typos throughout the code have been fixed. [omahs](https://github.com/omahs)
+
+
+
 ## v0.2.1 Rio
 
 ### Added

+ 1 - 1
Cargo.toml

@@ -28,7 +28,7 @@ tiny-keccak = { version = "2.0", features = ["keccak"] }
 serde_json = "1.0"
 serde = "1.0"
 serde_derive = { version = "1.0" }
-inkwell = { version = "0.1.0", features = ["target-webassembly", "target-bpf", "no-libffi-linking", "llvm14-0"], optional = true }
+inkwell = { version = "0.1.0", features = ["target-webassembly", "target-bpf", "no-libffi-linking", "llvm15-0"], optional = true }
 blake2-rfc = "0.2.18"
 handlebars = "4.3"
 contract-metadata = "1.5.1"

+ 3 - 4
Dockerfile

@@ -1,9 +1,8 @@
-FROM ghcr.io/hyperledger/solang:ci as builder
+FROM ghcr.io/hyperledger/solang-llvm:ci as builder
 
 COPY . src
-# TODO: bigint.c does not compile with llvm 14.0, disable for now
-# WORKDIR /src/stdlib/
-# RUN make
+WORKDIR /src/stdlib/
+RUN make
 
 RUN rustup default 1.64.0
 

+ 12 - 12
docs/installing.rst

@@ -121,40 +121,40 @@ Linux
 ~~~~~
 
 A pre-built version of LLVM, specifically configured for Solang, is available at
-`<https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-linux-x86-64.tar.xz>`_ for x86 processors
-and at `<https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-linux-arm64.tar.xz>`_ for ARM.
+`<https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-linux-x86-64.tar.xz>`_ for x86 processors
+and at `<https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-linux-arm64.tar.xz>`_ for ARM.
 After downloading, untar the file in a terminal and add it to your path.
 
 .. code-block:: bash
 
-	tar Jxf llvm14.0-linux-x86-64.tar.xz
-	export PATH=$(pwd)/llvm14.0/bin:$PATH
+	tar Jxf llvm15.0-linux-x86-64.tar.xz
+	export PATH=$(pwd)/llvm15.0/bin:$PATH
 
 Windows
 ~~~~~~~
 
 A pre-built version of LLVM, specifically configured for Solang, is available at
-`<https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-win.zip>`_.
+`<https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-win.zip>`_.
 
 After unzipping the file, add the bin directory to your path.
 
 .. code-block:: batch
 
-	set PATH=%PATH%;C:\llvm14.0\bin
+	set PATH=%PATH%;C:\llvm15.0\bin
 
 Mac
 ~~~
 
 A pre-built version of LLVM for intel macs, is available at
-`<https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-mac-intel.tar.xz>`_ and for arm macs there is
-`<https://github.com/hyperledger/solang/releases/download/v0.2.1/llvm14.0-mac-arm.tar.xz>`_. After downloading,
+`<https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-intel.tar.xz>`_ and for arm macs there is
+`<https://github.com/hyperledger/solang-llvm/releases/download/llvm15-0/llvm15.0-mac-arm.tar.xz>`_. After downloading,
 untar the file in a terminal and add it to your path like so:
 
 .. code-block:: bash
 
-	tar Jxf llvm14.0-mac-arm.tar.xz
-	xattr -rd com.apple.quarantine llvm14.0
-	export PATH=$(pwd)/llvm14.0/bin:$PATH
+	tar Jxf llvm15.0-mac-arm.tar.xz
+	xattr -rd com.apple.quarantine llvm15.0
+	export PATH=$(pwd)/llvm15.0/bin:$PATH
 
 .. _llvm-from-source:
 
@@ -166,7 +166,7 @@ you may need to consult. First if all clone our LLVM repository:
 
 .. code-block:: bash
 
-	git clone --depth 1 --branch solana-rustc/14.0-2022-03-22 https://github.com/solana-labs/llvm-project
+	git clone --depth 1 --branch solana-rustc/15.0-2022-08-09 https://github.com/solana-labs/llvm-project
 	cd llvm-project
 
 Now run cmake to create the makefiles. Replace the *installdir* argument to ``CMAKE_INSTALL_PREFIX`` with with a directory where you would like to have LLVM installed, and then run the build:

+ 2 - 2
src/codegen/dispatch.rs

@@ -44,7 +44,7 @@ pub(super) fn function_dispatch(
             loc: Loc::Codegen,
             expr: Expression::Load(
                 Loc::Codegen,
-                Type::Ref(Type::BufferPointer.into()),
+                Type::BufferPointer,
                 Expression::StructMember(
                     Loc::Codegen,
                     Type::Ref(Type::BufferPointer.into()),
@@ -66,7 +66,7 @@ pub(super) fn function_dispatch(
             loc: Loc::Codegen,
             expr: Expression::Load(
                 Loc::Codegen,
-                Type::Ref(Type::Uint(64).into()),
+                Type::Uint(64),
                 Expression::StructMember(
                     Loc::Codegen,
                     Type::Ref(Type::Uint(64).into()),

+ 6 - 6
src/codegen/encoding/mod.rs

@@ -323,7 +323,7 @@ pub(super) trait AbiEncoding {
 
         let qty = struct_ty.definition(ns).fields.len();
         let first_ty = struct_ty.definition(ns).fields[0].ty.clone();
-        let loaded = load_struct_member(first_ty, expr.clone(), 0);
+        let loaded = load_struct_member(first_ty, expr.clone(), 0, ns);
 
         let mut advance = self.encode(&loaded, buffer, &offset, arg_no, ns, vartab, cfg);
         let mut runtime_size = advance.clone();
@@ -336,7 +336,7 @@ pub(super) trait AbiEncoding {
                 offset.clone().into(),
                 advance.into(),
             );
-            let loaded = load_struct_member(ith_type.clone(), expr.clone(), i);
+            let loaded = load_struct_member(ith_type.clone(), expr.clone(), i, ns);
             // After fetching the struct member, we can encode it
             advance = self.encode(&loaded, buffer, &offset, arg_no, ns, vartab, cfg);
             runtime_size = Expression::Add(
@@ -812,11 +812,11 @@ pub(super) trait AbiEncoding {
             return Expression::NumberLiteral(Codegen, Uint(32), struct_size);
         }
         let first_type = struct_ty.definition(ns).fields[0].ty.clone();
-        let first_field = load_struct_member(first_type, expr.clone(), 0);
+        let first_field = load_struct_member(first_type, expr.clone(), 0, ns);
         let mut size = self.get_expr_size(arg_no, &first_field, ns, vartab, cfg);
         for i in 1..struct_ty.definition(ns).fields.len() {
             let ty = struct_ty.definition(ns).fields[i].ty.clone();
-            let field = load_struct_member(ty.clone(), expr.clone(), i);
+            let field = load_struct_member(ty.clone(), expr.clone(), i, ns);
             let expr_size = self.get_expr_size(arg_no, &field, ns, vartab, cfg).into();
             size = Expression::Add(Codegen, Uint(32), false, size.clone().into(), expr_size);
         }
@@ -1077,8 +1077,8 @@ fn finish_array_loop(for_loop: &ForLoop, vartab: &mut Vartable, cfg: &mut Contro
 }
 
 /// Loads a struct member
-fn load_struct_member(ty: Type, expr: Expression, field: usize) -> Expression {
-    if ty.is_fixed_reference_type() {
+fn load_struct_member(ty: Type, expr: Expression, field: usize, ns: &Namespace) -> Expression {
+    if ty.is_fixed_reference_type(ns) {
         // We should not dereference a struct or fixed array
         return Expression::StructMember(Codegen, ty, expr.into(), field);
     }

+ 1 - 1
src/codegen/expression.rs

@@ -2278,7 +2278,7 @@ pub fn assign_single(
             let dest = expression(left, cfg, contract_no, func, ns, vartab, opt);
 
             let cfg_right =
-                if !left_ty.is_contract_storage() && cfg_right.ty().is_fixed_reference_type() {
+                if !left_ty.is_contract_storage() && cfg_right.ty().is_fixed_reference_type(ns) {
                     Expression::Load(pt::Loc::Codegen, cfg_right.ty(), Box::new(cfg_right))
                 } else {
                     cfg_right

+ 37 - 83
src/emit/binary.rs

@@ -2,7 +2,6 @@
 
 use crate::sema::ast::{ArrayLength, Contract, Namespace, StructType, Type};
 use std::cell::RefCell;
-use std::ffi::CStr;
 use std::path::Path;
 use std::str;
 
@@ -334,11 +333,7 @@ impl<'a> Binary<'a> {
             gv.set_unnamed_addr(true);
         }
 
-        self.builder.build_pointer_cast(
-            gv.as_pointer_value(),
-            self.context.i8_type().ptr_type(AddressSpace::default()),
-            name,
-        )
+        gv.as_pointer_value()
     }
 
     /// Wrapper for alloca. Ensures that the alloca is done on the first basic block.
@@ -828,7 +823,6 @@ impl<'a> Binary<'a> {
                 Type::ExternalFunction { .. } => {
                     let address = self.llvm_type(&Type::Address(false), ns);
                     let selector = self.llvm_type(&Type::FunctionSelector, ns);
-
                     self.context
                         .struct_type(&[selector, address], false)
                         .as_basic_type_enum()
@@ -914,67 +908,32 @@ impl<'a> Binary<'a> {
                 "len",
             )
         } else {
-            let struct_ty = vector
-                .into_pointer_value()
-                .get_type()
-                .get_element_type()
-                .into_struct_type();
-            let name = struct_ty.get_name().unwrap();
-
-            if name == CStr::from_bytes_with_nul(b"struct.SolAccountInfo\0").unwrap() {
-                // load the data pointer
-                let data = self
-                    .builder
-                    .build_load(
-                        self.builder
-                            .build_struct_gep(vector.into_pointer_value(), 3, "data")
-                            .unwrap(),
-                        "data",
-                    )
-                    .into_pointer_value();
-
-                // get the offset of the return data
-                let header_ptr = self.builder.build_pointer_cast(
-                    data,
-                    self.context.i32_type().ptr_type(AddressSpace::default()),
-                    "header_ptr",
-                );
-
-                let data_len_ptr = unsafe {
-                    self.builder.build_gep(
-                        header_ptr,
-                        &[self.context.i64_type().const_int(1, false)],
-                        "data_len_ptr",
-                    )
-                };
+            // field 0 is the length
+            let vector = vector.into_pointer_value();
+            let vector_type = self.module.get_struct_type("struct.vector").unwrap();
 
-                self.builder
-                    .build_load(data_len_ptr, "len")
-                    .into_int_value()
-            } else {
-                // field 0 is the length
-                let vector = vector.into_pointer_value();
-
-                let len = unsafe {
-                    self.builder.build_gep(
-                        vector,
-                        &[
-                            self.context.i32_type().const_zero(),
-                            self.context.i32_type().const_zero(),
-                        ],
-                        "vector_len",
-                    )
-                };
-
-                self.builder
-                    .build_select(
-                        self.builder.build_is_null(vector, "vector_is_null"),
+            let len = unsafe {
+                self.builder.build_gep(
+                    vector_type,
+                    vector,
+                    &[
                         self.context.i32_type().const_zero(),
-                        self.builder.build_load(len, "vector_len").into_int_value(),
-                        "length",
-                    )
-                    .into_int_value()
-            }
+                        self.context.i32_type().const_zero(),
+                    ],
+                    "vector_len",
+                )
+            };
+
+            self.builder
+                .build_select(
+                    self.builder.build_is_null(vector, "vector_is_null"),
+                    self.context.i32_type().const_zero(),
+                    self.builder
+                        .build_load(self.context.i32_type(), len, "vector_len")
+                        .into_int_value(),
+                    "length",
+                )
+                .into_int_value()
         }
     }
 
@@ -983,14 +942,15 @@ impl<'a> Binary<'a> {
         if vector.is_struct_value() {
             // slice
             let slice = vector.into_struct_value();
-
             self.builder
                 .build_extract_value(slice, 0, "slice_data")
                 .unwrap()
                 .into_pointer_value()
         } else {
-            let data = unsafe {
+            let vector_type = self.module.get_struct_type("struct.vector").unwrap();
+            unsafe {
                 self.builder.build_gep(
+                    vector_type,
                     vector.into_pointer_value(),
                     &[
                         self.context.i32_type().const_zero(),
@@ -998,13 +958,7 @@ impl<'a> Binary<'a> {
                     ],
                     "data",
                 )
-            };
-
-            self.builder.build_pointer_cast(
-                data,
-                self.context.i8_type().ptr_type(AddressSpace::default()),
-                "data",
-            )
+            }
         }
     }
 
@@ -1020,8 +974,10 @@ impl<'a> Binary<'a> {
             Type::Array(_, dim) => {
                 if matches!(dim.last(), Some(ArrayLength::Fixed(_))) {
                     // fixed size array
+                    let llvm_ty = self.llvm_type(array_ty, ns);
                     unsafe {
                         self.builder.build_gep(
+                            llvm_ty,
                             array,
                             &[self.context.i32_type().const_zero(), index],
                             "index_access",
@@ -1029,22 +985,23 @@ impl<'a> Binary<'a> {
                     }
                 } else {
                     let elem_ty = array_ty.array_deref();
-                    let llvm_elem_ty = self.llvm_field_ty(&elem_ty, ns);
+                    let llvm_elem_ty = self.llvm_type(elem_ty.deref_memory(), ns);
 
                     // dynamic length array or vector
                     let index = self.builder.build_int_mul(
                         index,
                         llvm_elem_ty
-                            .into_pointer_type()
-                            .get_element_type()
                             .size_of()
                             .unwrap()
                             .const_cast(self.context.i32_type(), false),
                         "",
                     );
 
-                    let elem = unsafe {
+                    let vector_type = self.module.get_struct_type("struct.vector").unwrap();
+
+                    unsafe {
                         self.builder.build_gep(
+                            vector_type,
                             array,
                             &[
                                 self.context.i32_type().const_zero(),
@@ -1053,10 +1010,7 @@ impl<'a> Binary<'a> {
                             ],
                             "index_access",
                         )
-                    };
-
-                    self.builder
-                        .build_pointer_cast(elem, llvm_elem_ty.into_pointer_type(), "elem")
+                    }
                 }
             }
             _ => unreachable!(),

+ 101 - 217
src/emit/expression.rs

@@ -79,15 +79,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 .unwrap()
                 .into_pointer_value();
 
-            let s = bin.builder.build_pointer_cast(
-                s,
-                struct_ty.ptr_type(AddressSpace::default()),
-                "struct_literal",
-            );
-
             for (i, expr) in exprs.iter().enumerate() {
                 let elemptr = unsafe {
                     bin.builder.build_gep(
+                        struct_ty,
                         s,
                         &[
                             bin.context.i32_type().const_zero(),
@@ -99,8 +94,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 let elem = expression(target, bin, expr, vartab, function, ns);
 
-                let elem = if expr.ty().is_fixed_reference_type() {
-                    bin.builder.build_load(elem.into_pointer_value(), "elem")
+                let elem = if expr.ty().is_fixed_reference_type(ns) {
+                    let load_type = bin.llvm_type(&expr.ty(), ns);
+                    bin.builder
+                        .build_load(load_type, elem.into_pointer_value(), "elem")
                 } else {
                     elem
                 };
@@ -262,7 +259,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 let quotient = bin
                     .builder
-                    .build_load(quotient, "quotient")
+                    .build_load(ty, quotient, "quotient")
                     .into_int_value();
 
                 if bits < div_bits {
@@ -357,7 +354,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 let quotient = bin
                     .builder
-                    .build_load(quotient, "quotient")
+                    .build_load(ty, quotient, "quotient")
                     .into_int_value();
 
                 if bits < div_bits {
@@ -498,7 +495,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 bin.builder.position_at_end(success_block);
 
-                let rem = bin.builder.build_load(rem, "urem").into_int_value();
+                let rem = bin.builder.build_load(ty, rem, "urem").into_int_value();
 
                 if bits < div_bits {
                     bin.builder
@@ -590,7 +587,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 bin.builder.position_at_end(success_block);
 
-                let rem = bin.builder.build_load(rem, "srem").into_int_value();
+                let rem = bin.builder.build_load(ty, rem, "srem").into_int_value();
 
                 if bits < div_bits {
                     bin.builder
@@ -671,7 +668,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 .unwrap();
 
             // Load the result pointer
-            let res = bin.builder.build_load(o, "");
+            let res = bin.builder.build_load(left.get_type(), o, "");
 
             if !bin.options.math_overflow_check || *unchecked || ns.target != Target::Solana {
                 // In Substrate, overflow case will hit an unreachable expression, so no additional checks are needed.
@@ -849,9 +846,9 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
         Expression::Load(_, ty, e) => {
             let ptr = expression(target, bin, e, vartab, function, ns).into_pointer_value();
 
-            let value = bin.builder.build_load(ptr, "");
-
-            if ty.is_reference_type(ns) && !ty.is_fixed_reference_type() {
+            if ty.is_reference_type(ns) && !ty.is_fixed_reference_type(ns) {
+                let loaded_type = bin.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                let value = bin.builder.build_load(loaded_type, ptr, "");
                 // if the pointer is null, it needs to be allocated
                 let allocation_needed = bin
                     .builder
@@ -893,12 +890,6 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                     .unwrap()
                     .into_pointer_value();
 
-                let new_struct = bin.builder.build_pointer_cast(
-                    new_struct,
-                    llvm_ty.ptr_type(AddressSpace::default()),
-                    &format!("new_{}", ty.to_string(ns)),
-                );
-
                 bin.builder.build_store(ptr, new_struct);
 
                 bin.builder.build_unconditional_branch(already_allocated);
@@ -915,7 +906,8 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 combined_struct_ptr.as_basic_value()
             } else {
-                value
+                let loaded_type = bin.llvm_type(ty, ns);
+                bin.builder.build_load(loaded_type, ptr, "")
             }
         }
 
@@ -965,16 +957,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             // Swap the byte order
             let bytes_ptr = bin.build_alloca(function, e.get_type(), "bytes_ptr");
             bin.builder.build_store(bytes_ptr, e);
-            let bytes_ptr = bin.builder.build_pointer_cast(
-                bytes_ptr,
-                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                "bytes_ptr",
-            );
-            let init = bin.builder.build_pointer_cast(
-                bin.build_alloca(function, e.get_type(), "init"),
-                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                "init",
-            );
+            let init = bin.build_alloca(function, e.get_type(), "init");
             bin.builder.build_call(
                 bin.module.get_function("__leNtobeN").unwrap(),
                 &[bytes_ptr.into(), init.into(), size.into()],
@@ -1028,20 +1011,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
             bin.builder.build_call(
                 bin.module.get_function("__beNtoleN").unwrap(),
-                &[
-                    bytes_ptr.into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            le_bytes_ptr,
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "le_bytes_ptr",
-                        )
-                        .into(),
-                    len.into(),
-                ],
+                &[bytes_ptr.into(), le_bytes_ptr.into(), len.into()],
                 "",
             );
-            bin.builder.build_load(le_bytes_ptr, "bytes")
+            bin.builder.build_load(ty, le_bytes_ptr, "bytes")
         }
         Expression::Not(_, e) => {
             let e = expression(target, bin, e, vartab, function, ns).into_int_value();
@@ -1105,16 +1078,15 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 let array = expression(target, bin, a, vartab, function, ns).into_pointer_value();
                 let index = expression(target, bin, i, vartab, function, ns).into_int_value();
 
+                let llvm_ty = bin.module.get_struct_type("struct.SolAccountInfo").unwrap();
                 unsafe {
                     bin.builder
-                        .build_gep(array, &[index], "account_info")
+                        .build_gep(llvm_ty, array, &[index], "account_info")
                         .into()
                 }
             } else if ty.is_dynamic_memory() {
                 let array = expression(target, bin, a, vartab, function, ns);
 
-                let ty = bin.llvm_field_ty(elem_ty, ns);
-
                 let mut array_index =
                     expression(target, bin, i, vartab, function, ns).into_int_value();
 
@@ -1129,29 +1101,31 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 let index = bin.builder.build_int_mul(
                     array_index,
-                    ty.into_pointer_type()
-                        .get_element_type()
+                    bin.llvm_type(elem_ty.deref_memory(), ns)
                         .size_of()
                         .unwrap()
                         .const_cast(bin.context.i32_type(), false),
                     "",
                 );
 
-                let elem = unsafe {
-                    bin.builder
-                        .build_gep(bin.vector_bytes(array), &[index], "index_access")
-                };
-
-                bin.builder
-                    .build_pointer_cast(elem, ty.into_pointer_type(), "elem")
-                    .into()
+                unsafe {
+                    bin.builder.build_gep(
+                        bin.context.i8_type(),
+                        bin.vector_bytes(array),
+                        &[index],
+                        "index_access",
+                    )
+                }
+                .into()
             } else {
                 let array = expression(target, bin, a, vartab, function, ns).into_pointer_value();
                 let index = expression(target, bin, i, vartab, function, ns).into_int_value();
 
+                let llvm_ty = bin.llvm_type(ty.deref_memory(), ns);
                 unsafe {
                     bin.builder
                         .build_gep(
+                            llvm_ty,
                             array,
                             &[bin.context.i32_type().const_zero(), index],
                             "index_access",
@@ -1166,10 +1140,11 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             target.builtin(bin, e, vartab, function, ns)
         }
         Expression::StructMember(_, _, a, i) => {
+            let struct_ty = bin.llvm_type(a.ty().deref_memory(), ns);
             let struct_ptr = expression(target, bin, a, vartab, function, ns).into_pointer_value();
 
             bin.builder
-                .build_struct_gep(struct_ptr, *i as u32, "struct member")
+                .build_struct_gep(struct_ty, struct_ptr, *i as u32, "struct member")
                 .unwrap()
                 .into()
         }
@@ -1235,12 +1210,6 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 .left()
                 .unwrap();
 
-            let array = bin.builder.build_pointer_cast(
-                p.into_pointer_value(),
-                ty.ptr_type(AddressSpace::default()),
-                "array_literal",
-            );
-
             for (i, expr) in exprs.iter().enumerate() {
                 let mut ind = vec![bin.context.i32_type().const_zero()];
 
@@ -1252,12 +1221,17 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                     e /= *d;
                 }
 
-                let elemptr = unsafe { bin.builder.build_gep(array, &ind, &format!("elemptr{i}")) };
+                let elemptr = unsafe {
+                    bin.builder
+                        .build_gep(ty, p.into_pointer_value(), &ind, &format!("elemptr{i}"))
+                };
 
                 let elem = expression(target, bin, expr, vartab, function, ns);
 
-                let elem = if expr.ty().is_fixed_reference_type() {
-                    bin.builder.build_load(elem.into_pointer_value(), "elem")
+                let elem = if expr.ty().is_fixed_reference_type(ns) {
+                    let load_type = bin.llvm_type(&expr.ty(), ns);
+                    bin.builder
+                        .build_load(load_type, elem.into_pointer_value(), "elem")
                 } else {
                     elem
                 };
@@ -1265,7 +1239,7 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 bin.builder.build_store(elemptr, elem);
             }
 
-            array.into()
+            p
         }
         Expression::AllocDynamicBytes(_, ty, size, init) => {
             if matches!(ty, Type::Slice(_)) {
@@ -1317,47 +1291,30 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
                 v.into_pointer_value()
             };
 
-            let start = unsafe { bin.builder.build_gep(data, &[offset], "start") };
+            let start = unsafe {
+                bin.builder
+                    .build_gep(bin.context.i8_type(), data, &[offset], "start")
+            };
 
             if matches!(returns[0], Type::Bytes(_) | Type::FunctionSelector) {
                 let n = returns[0].bytes(ns);
+                let bytes_ty = bin.context.custom_width_int_type(n as u32 * 8);
 
-                let store = bin.build_alloca(
-                    function,
-                    bin.context.custom_width_int_type(n as u32 * 8),
-                    "stack",
-                );
+                let store = bin.build_alloca(function, bytes_ty, "stack");
                 bin.builder.build_call(
                     bin.module.get_function("__beNtoleN").unwrap(),
                     &[
-                        bin.builder
-                            .build_pointer_cast(
-                                start,
-                                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                "",
-                            )
-                            .into(),
-                        bin.builder
-                            .build_pointer_cast(
-                                store,
-                                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                "",
-                            )
-                            .into(),
+                        start.into(),
+                        store.into(),
                         bin.context.i32_type().const_int(n as u64, false).into(),
                     ],
                     "",
                 );
-                bin.builder.build_load(store, &format!("bytes{n}"))
+                bin.builder
+                    .build_load(bytes_ty, store, &format!("bytes{n}"))
             } else {
-                let start = bin.builder.build_pointer_cast(
-                    start,
-                    bin.llvm_type(&returns[0], ns)
-                        .ptr_type(AddressSpace::default()),
-                    "start",
-                );
-
-                bin.builder.build_load(start, "value")
+                bin.builder
+                    .build_load(bin.llvm_type(&returns[0], ns), start, "value")
             }
         }
         Expression::Keccak256(_, _, exprs) => {
@@ -1391,7 +1348,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             let mut offset = bin.context.i32_type().const_zero();
 
             for (v, len, ty) in values {
-                let elem = unsafe { bin.builder.build_gep(src, &[offset], "elem") };
+                let elem = unsafe {
+                    bin.builder
+                        .build_gep(bin.context.i8_type(), src, &[offset], "elem")
+                };
 
                 offset = bin.builder.build_int_add(offset, len, "");
 
@@ -1401,38 +1361,21 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
                         bin.builder.build_call(
                             bin.module.get_function("__memcpy").unwrap(),
-                            &[
-                                elem.into(),
-                                bin.builder
-                                    .build_pointer_cast(
-                                        data,
-                                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                        "data",
-                                    )
-                                    .into(),
-                                len.into(),
-                            ],
+                            &[elem.into(), data.into(), len.into()],
                             "",
                         );
                     }
                     _ => {
-                        let elem = bin.builder.build_pointer_cast(
-                            elem,
-                            v.get_type().ptr_type(AddressSpace::default()),
-                            "",
-                        );
-
                         bin.builder.build_store(elem, v);
                     }
                 }
             }
-            let dst = bin
-                .builder
-                .build_alloca(bin.context.custom_width_int_type(256), "keccak_dst");
+            let dst_type = bin.context.custom_width_int_type(256);
+            let dst = bin.builder.build_alloca(dst_type, "keccak_dst");
 
             target.keccak256_hash(bin, src, length, dst, ns);
 
-            bin.builder.build_load(dst, "keccak256_hash")
+            bin.builder.build_load(dst_type, dst, "keccak256_hash")
         }
         Expression::StringCompare(_, l, r) => {
             let (left, left_len) = string_location(target, bin, l, vartab, function, ns);
@@ -1490,32 +1433,21 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             .into(),
         Expression::Builtin(_, _, Builtin::Signature, _) if ns.target != Target::Solana => {
             // need to byte-reverse selector
-            let selector = bin.build_alloca(function, bin.context.i32_type(), "selector");
+            let selector_type = bin.context.i32_type();
+            let selector = bin.build_alloca(function, selector_type, "selector");
 
             // byte order needs to be reversed. e.g. hex"11223344" should be 0x10 0x11 0x22 0x33 0x44
             bin.builder.build_call(
                 bin.module.get_function("__beNtoleN").unwrap(),
                 &[
-                    bin.builder
-                        .build_pointer_cast(
-                            bin.selector.as_pointer_value(),
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "",
-                        )
-                        .into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            selector,
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "",
-                        )
-                        .into(),
+                    bin.selector.as_pointer_value().into(),
+                    selector.into(),
                     bin.context.i32_type().const_int(4, false).into(),
                 ],
                 "",
             );
 
-            bin.builder.build_load(selector, "selector")
+            bin.builder.build_load(selector_type, selector, "selector")
         }
         Expression::Builtin(_, _, Builtin::AddMod, args) => {
             let arith_ty = bin.context.custom_width_int_type(512);
@@ -1584,7 +1516,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             bin.builder.build_return(Some(&ret));
             bin.builder.position_at_end(success_block);
 
-            let remainder = bin.builder.build_load(rem, "remainder").into_int_value();
+            let remainder = bin
+                .builder
+                .build_load(arith_ty, rem, "remainder")
+                .into_int_value();
 
             bin.builder
                 .build_int_truncate(remainder, res_ty, "quotient")
@@ -1608,33 +1543,15 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             bin.builder.build_call(
                 bin.module.get_function("__mul32").unwrap(),
                 &[
-                    bin.builder
-                        .build_pointer_cast(
-                            x_m,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "left",
-                        )
-                        .into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            y_m,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "right",
-                        )
-                        .into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            x_times_y_m,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "output",
-                        )
-                        .into(),
+                    x_m.into(),
+                    y_m.into(),
+                    x_times_y_m.into(),
                     bin.context.i32_type().const_int(512 / 32, false).into(),
                 ],
                 "",
             );
             let k = expression(target, bin, &args[2], vartab, function, ns).into_int_value();
-            let dividend = bin.builder.build_load(x_times_y_m, "x_t_y");
+            let dividend = bin.builder.build_load(arith_ty, x_times_y_m, "x_t_y");
 
             let divisor = bin.builder.build_int_z_extend(k, arith_ty, "wide_k");
 
@@ -1691,7 +1608,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
 
             bin.builder.position_at_end(success_block);
 
-            let remainder = bin.builder.build_load(rem, "quotient").into_int_value();
+            let remainder = bin
+                .builder
+                .build_load(arith_ty, rem, "quotient")
+                .into_int_value();
 
             bin.builder
                 .build_int_truncate(remainder, res_ty, "quotient")
@@ -1742,7 +1662,10 @@ pub(super) fn expression<'a, T: TargetRuntime<'a> + ?Sized>(
             };
             let offset =
                 expression(target, bin, bytes_offset, vartab, function, ns).into_int_value();
-            let advanced = unsafe { bin.builder.build_gep(pointer, &[offset], "adv_pointer") };
+            let advanced = unsafe {
+                bin.builder
+                    .build_gep(bin.context.i8_type(), pointer, &[offset], "adv_pointer")
+            };
 
             advanced.into()
         }
@@ -1781,22 +1704,8 @@ pub(super) fn compare_address<'a, T: TargetRuntime<'a> + ?Sized>(
         .build_call(
             binary.module.get_function("__memcmp_ord").unwrap(),
             &[
-                binary
-                    .builder
-                    .build_pointer_cast(
-                        left,
-                        binary.context.i8_type().ptr_type(AddressSpace::default()),
-                        "left",
-                    )
-                    .into(),
-                binary
-                    .builder
-                    .build_pointer_cast(
-                        right,
-                        binary.context.i8_type().ptr_type(AddressSpace::default()),
-                        "right",
-                    )
-                    .into(),
+                left.into(),
+                right.into(),
                 binary
                     .context
                     .i32_type()
@@ -1844,27 +1753,11 @@ fn runtime_cast<'a>(
 
         bin.builder.build_call(
             bin.module.get_function("__leNtobeN").unwrap(),
-            &[
-                bin.builder
-                    .build_pointer_cast(
-                        src,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "address_ptr",
-                    )
-                    .into(),
-                bin.builder
-                    .build_pointer_cast(
-                        dest,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "dest_ptr",
-                    )
-                    .into(),
-                len.into(),
-            ],
+            &[src.into(), dest.into(), len.into()],
             "",
         );
 
-        bin.builder.build_load(dest, "val")
+        bin.builder.build_load(bin.address_type(ns), dest, "val")
     } else if let Type::Address(_) = from {
         let llvm_ty = bin.llvm_type(to, ns);
 
@@ -1881,27 +1774,11 @@ fn runtime_cast<'a>(
 
         bin.builder.build_call(
             bin.module.get_function("__beNtoleN").unwrap(),
-            &[
-                bin.builder
-                    .build_pointer_cast(
-                        src,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "address_ptr",
-                    )
-                    .into(),
-                bin.builder
-                    .build_pointer_cast(
-                        dest,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "dest_ptr",
-                    )
-                    .into(),
-                len.into(),
-            ],
+            &[src.into(), dest.into(), len.into()],
             "",
         );
 
-        bin.builder.build_load(dest, "val")
+        bin.builder.build_load(llvm_ty, dest, "val")
     } else if matches!(from, Type::Bool) && matches!(to, Type::Int(_) | Type::Uint(_)) {
         bin.builder
             .build_int_cast(
@@ -1930,11 +1807,15 @@ fn runtime_cast<'a>(
             )
             .into()
     } else if matches!((from, to), (Type::DynamicBytes, Type::Slice(_))) {
-        let slice = bin.build_alloca(function, bin.llvm_type(to, ns), "slice");
+        let slice_ty = bin.llvm_type(to, ns);
+        let slice = bin.build_alloca(function, slice_ty, "slice");
 
         let data = bin.vector_bytes(val);
 
-        let data_ptr = bin.builder.build_struct_gep(slice, 0, "data").unwrap();
+        let data_ptr = bin
+            .builder
+            .build_struct_gep(slice_ty, slice, 0, "data")
+            .unwrap();
 
         bin.builder.build_store(data_ptr, data);
 
@@ -1942,11 +1823,14 @@ fn runtime_cast<'a>(
             bin.builder
                 .build_int_z_extend(bin.vector_len(val), bin.context.i64_type(), "len");
 
-        let len_ptr = bin.builder.build_struct_gep(slice, 1, "len").unwrap();
+        let len_ptr = bin
+            .builder
+            .build_struct_gep(slice_ty, slice, 1, "len")
+            .unwrap();
 
         bin.builder.build_store(len_ptr, len);
 
-        bin.builder.build_load(slice, "slice")
+        bin.builder.build_load(slice_ty, slice, "slice")
     } else {
         val
     }

+ 105 - 208
src/emit/instructions.rs

@@ -11,9 +11,7 @@ use crate::emit::{ContractArgs, TargetRuntime};
 use crate::sema::ast::{Contract, Namespace, RetrieveType, Type};
 use crate::Target;
 use inkwell::types::BasicType;
-use inkwell::values::{
-    BasicMetadataValueEnum, BasicValueEnum, CallableValue, FunctionValue, IntValue,
-};
+use inkwell::values::{BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue};
 use inkwell::{AddressSpace, IntPredicate};
 use num_traits::ToPrimitive;
 use solang_parser::pt::CodeLocation;
@@ -201,33 +199,20 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 .builder
                 .build_call(
                     bin.module.get_function("__realloc").unwrap(),
-                    &[
-                        bin.builder
-                            .build_pointer_cast(
-                                arr.into_pointer_value(),
-                                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                "a",
-                            )
-                            .into(),
-                        realloc_size.into(),
-                    ],
+                    &[arr.into(), realloc_size.into()],
                     "",
                 )
                 .try_as_basic_value()
                 .left()
                 .unwrap()
                 .into_pointer_value();
-            let dest = bin.builder.build_pointer_cast(
-                new,
-                llvm_ty.ptr_type(AddressSpace::default()),
-                "dest",
-            );
-            w.vars.get_mut(array).unwrap().value = dest.into();
+            w.vars.get_mut(array).unwrap().value = new.into();
 
             // Store the value into the last element
             let slot_ptr = unsafe {
                 bin.builder.build_gep(
-                    dest,
+                    llvm_ty,
+                    new,
                     &[
                         bin.context.i32_type().const_zero(),
                         bin.context.i32_type().const_int(2, false),
@@ -237,24 +222,22 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 )
             };
             let value = expression(target, bin, value, &w.vars, function, ns);
-            let elem_ptr = bin.builder.build_pointer_cast(
-                slot_ptr,
-                llvm_elem_ty.ptr_type(AddressSpace::default()),
-                "element pointer",
-            );
-            let value = if elem_ty.is_fixed_reference_type() {
-                w.vars.get_mut(res).unwrap().value = elem_ptr.into();
-                bin.builder.build_load(value.into_pointer_value(), "elem")
+            let value = if elem_ty.is_fixed_reference_type(ns) {
+                w.vars.get_mut(res).unwrap().value = slot_ptr.into();
+                let load_ty = bin.llvm_type(&elem_ty, ns);
+                bin.builder
+                    .build_load(load_ty, value.into_pointer_value(), "elem")
             } else {
                 w.vars.get_mut(res).unwrap().value = value;
                 value
             };
-            bin.builder.build_store(elem_ptr, value);
+            bin.builder.build_store(slot_ptr, value);
 
             // Update the len and size field of the vector struct
             let len_ptr = unsafe {
                 bin.builder.build_gep(
-                    dest,
+                    llvm_ty,
+                    new,
                     &[
                         bin.context.i32_type().const_zero(),
                         bin.context.i32_type().const_zero(),
@@ -262,16 +245,12 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "len",
                 )
             };
-            let len_field = bin.builder.build_pointer_cast(
-                len_ptr,
-                bin.context.i32_type().ptr_type(AddressSpace::default()),
-                "len field",
-            );
-            bin.builder.build_store(len_field, new_len);
+            bin.builder.build_store(len_ptr, new_len);
 
             let size_ptr = unsafe {
                 bin.builder.build_gep(
-                    dest,
+                    llvm_ty,
+                    new,
                     &[
                         bin.context.i32_type().const_zero(),
                         bin.context.i32_type().const_int(1, false),
@@ -279,12 +258,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "size",
                 )
             };
-            let size_field = bin.builder.build_pointer_cast(
-                size_ptr,
-                bin.context.i32_type().ptr_type(AddressSpace::default()),
-                "size field",
-            );
-            bin.builder.build_store(size_field, new_len);
+            bin.builder.build_store(size_ptr, new_len);
         }
         Instr::PopMemory {
             res,
@@ -295,6 +269,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
             let a = w.vars[array].value.into_pointer_value();
             let len = unsafe {
                 bin.builder.build_gep(
+                    bin.module.get_struct_type("struct.vector").unwrap(),
                     a,
                     &[
                         bin.context.i32_type().const_zero(),
@@ -303,7 +278,10 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "a_len",
                 )
             };
-            let len = bin.builder.build_load(len, "a_len").into_int_value();
+            let len = bin
+                .builder
+                .build_load(bin.context.i32_type(), len, "a_len")
+                .into_int_value();
 
             // First check if the array is empty
             let is_array_empty = bin.builder.build_int_compare(
@@ -355,6 +333,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
             // Get the pointer to the last element and return it
             let slot_ptr = unsafe {
                 bin.builder.build_gep(
+                    bin.module.get_struct_type("struct.vector").unwrap(),
                     a,
                     &[
                         bin.context.i32_type().const_zero(),
@@ -364,24 +343,16 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "data",
                 )
             };
-            let slot_ptr = bin.builder.build_pointer_cast(
-                slot_ptr,
-                llvm_elem_ty.ptr_type(AddressSpace::default()),
-                "slot_ptr",
-            );
-            if elem_ty.is_fixed_reference_type() {
+            if elem_ty.is_fixed_reference_type(ns) {
                 w.vars.get_mut(res).unwrap().value = slot_ptr.into();
             } else {
-                let ret_val = bin.builder.build_load(slot_ptr, "");
+                let ret_val = bin
+                    .builder
+                    .build_load(bin.llvm_type(&elem_ty, ns), slot_ptr, "");
                 w.vars.get_mut(res).unwrap().value = ret_val;
             }
 
             // Reallocate and reassign the array pointer
-            let a = bin.builder.build_pointer_cast(
-                a,
-                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                "a",
-            );
 
             let realloc_size = if ns.target == Target::Solana {
                 bin.builder
@@ -401,17 +372,13 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 .left()
                 .unwrap()
                 .into_pointer_value();
-            let dest = bin.builder.build_pointer_cast(
-                new,
-                llvm_ty.ptr_type(AddressSpace::default()),
-                "dest",
-            );
-            w.vars.get_mut(array).unwrap().value = dest.into();
+            w.vars.get_mut(array).unwrap().value = new.into();
 
             // Update the len and size field of the vector struct
             let len_ptr = unsafe {
                 bin.builder.build_gep(
-                    dest,
+                    llvm_ty,
+                    new,
                     &[
                         bin.context.i32_type().const_zero(),
                         bin.context.i32_type().const_zero(),
@@ -419,16 +386,12 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "len",
                 )
             };
-            let len_field = bin.builder.build_pointer_cast(
-                len_ptr,
-                bin.context.i32_type().ptr_type(AddressSpace::default()),
-                "len field",
-            );
-            bin.builder.build_store(len_field, new_len);
+            bin.builder.build_store(len_ptr, new_len);
 
             let size_ptr = unsafe {
                 bin.builder.build_gep(
-                    dest,
+                    llvm_ty,
+                    new,
                     &[
                         bin.context.i32_type().const_zero(),
                         bin.context.i32_type().const_int(1, false),
@@ -436,12 +399,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "size",
                 )
             };
-            let size_field = bin.builder.build_pointer_cast(
-                size_ptr,
-                bin.context.i32_type().ptr_type(AddressSpace::default()),
-                "size field",
-            );
-            bin.builder.build_store(size_field, new_len);
+            bin.builder.build_store(size_ptr, new_len);
         }
         Instr::AssertFailure { encoded_args: None } => {
             target.assert_failure(
@@ -523,10 +481,12 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
             if !res.is_empty() {
                 for (i, v) in f.returns.iter().enumerate() {
-                    let val = bin
-                        .builder
-                        .build_load(parms[args.len() + i].into_pointer_value(), v.name_as_str());
-
+                    let load_ty = bin.llvm_var_ty(&v.ty, ns);
+                    let val = bin.builder.build_load(
+                        load_ty,
+                        parms[args.len() + i].into_pointer_value(),
+                        v.name_as_str(),
+                    );
                     let dest = w.vars[&res[i]].value;
 
                     if dest.is_pointer_value()
@@ -566,7 +526,8 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 }
             }
 
-            let ret = target.builtin_function(bin, function, callee, &parms, ns);
+            let first_arg_type = bin.llvm_type(&args[0].ty(), ns);
+            let ret = target.builtin_function(bin, function, callee, &parms, first_arg_type, ns);
 
             let success = bin.builder.build_int_compare(
                 IntPredicate::EQ,
@@ -587,9 +548,18 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
             if !res.is_empty() {
                 for (i, v) in callee.returns.iter().enumerate() {
-                    let val = bin
-                        .builder
-                        .build_load(parms[args.len() + i].into_pointer_value(), v.name_as_str());
+                    let load_ty = if v.ty.is_reference_type(ns) {
+                        bin.llvm_type(&v.ty, ns)
+                            .ptr_type(AddressSpace::default())
+                            .as_basic_type_enum()
+                    } else {
+                        bin.llvm_type(&v.ty, ns)
+                    };
+                    let val = bin.builder.build_load(
+                        load_ty,
+                        parms[args.len() + i].into_pointer_value(),
+                        v.name_as_str(),
+                    );
 
                     let dest = w.vars[&res[i]].value;
 
@@ -612,8 +582,11 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
         } => {
             let ty = call_expr.ty();
 
-            let returns = if let Type::InternalFunction { returns, .. } = ty.deref_any() {
-                returns
+            let (llvm_func, returns) = if let Type::InternalFunction {
+                params, returns, ..
+            } = ty.deref_any()
+            {
+                (bin.function_type(params, returns, ns), returns)
             } else {
                 panic!("should be Type::InternalFunction type");
             };
@@ -637,14 +610,12 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 parms.push(parameters.into());
             }
 
-            let callable = CallableValue::try_from(
-                expression(target, bin, call_expr, &w.vars, function, ns).into_pointer_value(),
-            )
-            .unwrap();
+            let callable =
+                expression(target, bin, call_expr, &w.vars, function, ns).into_pointer_value();
 
             let ret = bin
                 .builder
-                .build_call(callable, &parms, "")
+                .build_indirect_call(llvm_func, callable, &parms, "")
                 .try_as_basic_value()
                 .left()
                 .unwrap();
@@ -668,9 +639,12 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
             if !res.is_empty() {
                 for (i, ty) in returns.iter().enumerate() {
-                    let val = bin
-                        .builder
-                        .build_load(parms[args.len() + i].into_pointer_value(), "");
+                    let load_ty = bin.llvm_var_ty(ty, ns);
+                    let val = bin.builder.build_load(
+                        load_ty,
+                        parms[args.len() + i].into_pointer_value(),
+                        "",
+                    );
 
                     let dest = w.vars[&res[i]].value;
 
@@ -734,15 +708,17 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                         let val =
                             expression(target, bin, &exprs[i as usize], &w.vars, function, ns);
 
-                        let seed_count = val
-                            .get_type()
-                            .into_pointer_type()
-                            .get_element_type()
-                            .into_array_type()
-                            .len();
+                        let seed_count = exprs[i as usize]
+                            .ty()
+                            .deref_memory()
+                            .array_length()
+                            .unwrap()
+                            .to_u64()
+                            .unwrap();
 
                         let dest = unsafe {
                             bin.builder.build_gep(
+                                seeds_ty,
                                 output_seeds,
                                 &[
                                     bin.context.i32_type().const_int(i, false),
@@ -752,16 +728,11 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                             )
                         };
 
-                        let val = bin.builder.build_pointer_cast(
-                            val.into_pointer_value(),
-                            dest.get_type().get_element_type().into_pointer_type(),
-                            "seeds",
-                        );
-
                         bin.builder.build_store(dest, val);
 
                         let dest = unsafe {
                             bin.builder.build_gep(
+                                seeds_ty,
                                 output_seeds,
                                 &[
                                     bin.context.i32_type().const_int(i, false),
@@ -771,7 +742,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                             )
                         };
 
-                        let val = bin.context.i64_type().const_int(seed_count as u64, false);
+                        let val = bin.context.i64_type().const_int(seed_count, false);
 
                         bin.builder.build_store(dest, val);
                     }
@@ -792,11 +763,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 function,
                 success,
                 *contract_no,
-                bin.builder.build_pointer_cast(
-                    address_stack,
-                    bin.context.i8_type().ptr_type(AddressSpace::default()),
-                    "address",
-                ),
+                address_stack,
                 encoded_args,
                 encoded_args_len,
                 gas,
@@ -805,7 +772,9 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 *loc,
             );
 
-            w.vars.get_mut(res).unwrap().value = bin.builder.build_load(address_stack, "address");
+            w.vars.get_mut(res).unwrap().value =
+                bin.builder
+                    .build_load(bin.address_type(ns), address_stack, "address");
         }
         Instr::ExternalCall {
             success,
@@ -835,14 +804,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "address",
                 );
 
-                bin.builder.build_store(
-                    bin.builder.build_pointer_cast(
-                        addr,
-                        address.get_type().ptr_type(AddressSpace::default()),
-                        "address",
-                    ),
-                    address,
-                );
+                bin.builder.build_store(addr, address);
 
                 Some(addr)
             } else {
@@ -872,12 +834,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 (bin.vector_bytes(payload), bin.vector_len(payload))
             } else {
                 let ptr = payload.into_pointer_value();
-                let len = ptr
-                    .get_type()
-                    .get_element_type()
-                    .size_of()
-                    .unwrap()
-                    .const_cast(bin.context.i32_type(), false);
+                let len = bin.llvm_type(&payload_ty, ns).size_of().unwrap();
 
                 (ptr, len)
             };
@@ -901,15 +858,17 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                         let val =
                             expression(target, bin, &exprs[i as usize], &w.vars, function, ns);
 
-                        let seed_count = val
-                            .get_type()
-                            .into_pointer_type()
-                            .get_element_type()
-                            .into_array_type()
-                            .len();
+                        let seed_count = exprs[i as usize]
+                            .ty()
+                            .deref_any()
+                            .array_length()
+                            .unwrap()
+                            .to_u64()
+                            .unwrap();
 
                         let dest = unsafe {
                             bin.builder.build_gep(
+                                seeds_ty,
                                 output_seeds,
                                 &[
                                     bin.context.i32_type().const_int(i, false),
@@ -919,16 +878,11 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                             )
                         };
 
-                        let val = bin.builder.build_pointer_cast(
-                            val.into_pointer_value(),
-                            dest.get_type().get_element_type().into_pointer_type(),
-                            "seeds",
-                        );
-
                         bin.builder.build_store(dest, val);
 
                         let dest = unsafe {
                             bin.builder.build_gep(
+                                seeds_ty,
                                 output_seeds,
                                 &[
                                     bin.context.i32_type().const_int(i, false),
@@ -938,7 +892,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                             )
                         };
 
-                        let val = bin.context.i64_type().const_int(seed_count as u64, false);
+                        let val = bin.context.i64_type().const_int(seed_count, false);
 
                         bin.builder.build_store(dest, val);
                     }
@@ -982,32 +936,13 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
             let addr = bin.build_alloca(function, bin.address_type(ns), "address");
 
-            bin.builder.build_store(
-                bin.builder.build_pointer_cast(
-                    addr,
-                    address.get_type().ptr_type(AddressSpace::default()),
-                    "address",
-                ),
-                address,
-            );
+            bin.builder.build_store(addr, address);
             let success = match success {
                 Some(n) => Some(&mut w.vars.get_mut(n).unwrap().value),
                 None => None,
             };
 
-            target.value_transfer(
-                bin,
-                function,
-                success,
-                bin.builder.build_pointer_cast(
-                    addr,
-                    bin.context.i8_type().ptr_type(AddressSpace::default()),
-                    "address",
-                ),
-                value,
-                ns,
-                loc,
-            );
+            target.value_transfer(bin, function, success, addr, value, ns, loc);
         }
         Instr::AbiDecode {
             res,
@@ -1064,14 +999,7 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 let selector_data = bin
                     .builder
-                    .build_load(
-                        bin.builder.build_pointer_cast(
-                            data,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "selector",
-                        ),
-                        "selector",
-                    )
+                    .build_load(bin.context.i32_type(), data, "selector")
                     .into_int_value();
 
                 let selector = if ns.target.is_substrate() {
@@ -1102,11 +1030,8 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
 
                 data = unsafe {
                     bin.builder.build_gep(
-                        bin.builder.build_pointer_cast(
-                            data,
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "data",
-                        ),
+                        bin.context.i8_type(),
+                        data,
                         &[bin.context.i32_type().const_int(4, false)],
                         "data",
                     )
@@ -1158,7 +1083,10 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
             let offset = expression(target, bin, offset, &w.vars, function, ns).into_int_value();
             let emit_value = expression(target, bin, value, &w.vars, function, ns);
 
-            let start = unsafe { bin.builder.build_gep(data, &[offset], "start") };
+            let start = unsafe {
+                bin.builder
+                    .build_gep(bin.context.i8_type(), data, &[offset], "start")
+            };
 
             let is_bytes = if let Type::Bytes(n) = value.ty() {
                 n
@@ -1179,20 +1107,8 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                 bin.builder.build_call(
                     bin.module.get_function("__leNtobeN").unwrap(),
                     &[
-                        bin.builder
-                            .build_pointer_cast(
-                                value_ptr,
-                                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                "store",
-                            )
-                            .into(),
-                        bin.builder
-                            .build_pointer_cast(
-                                start,
-                                bin.context.i8_type().ptr_type(AddressSpace::default()),
-                                "dest",
-                            )
-                            .into(),
+                        value_ptr.into(),
+                        start.into(),
                         bin.context
                             .i32_type()
                             .const_int(is_bytes as u64, false)
@@ -1201,12 +1117,6 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
                     "",
                 );
             } else {
-                let start = bin.builder.build_pointer_cast(
-                    start,
-                    emit_value.get_type().ptr_type(AddressSpace::default()),
-                    "start",
-                );
-
                 bin.builder.build_store(start, emit_value);
             }
         }
@@ -1228,19 +1138,6 @@ pub(super) fn process_instruction<'a, T: TargetRuntime<'a> + ?Sized>(
             };
 
             let size = expression(target, bin, bytes, &w.vars, function, ns);
-            let arg_type = bin.context.i8_type().ptr_type(AddressSpace::default());
-
-            let src = if src.get_type() == arg_type {
-                src
-            } else {
-                bin.builder.build_pointer_cast(src, arg_type, "")
-            };
-
-            let dest = if dest.get_type() == arg_type {
-                dest
-            } else {
-                bin.builder.build_pointer_cast(dest, arg_type, "")
-            };
 
             bin.builder.build_call(
                 bin.module.get_function("__memcpy").unwrap(),

+ 15 - 68
src/emit/math.rs

@@ -75,27 +75,9 @@ fn signed_ovf_detect<'b, 'a: 'b, T: TargetRuntime<'a> + ?Sized>(
     let return_val = bin.builder.build_call(
         bin.module.get_function("__mul32_with_builtin_ovf").unwrap(),
         &[
-            bin.builder
-                .build_pointer_cast(
-                    l,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "left",
-                )
-                .into(),
-            bin.builder
-                .build_pointer_cast(
-                    r,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "right",
-                )
-                .into(),
-            bin.builder
-                .build_pointer_cast(
-                    o,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "output",
-                )
-                .into(),
+            l.into(),
+            r.into(),
+            o.into(),
             bin.context
                 .i32_type()
                 .const_int(mul_bits as u64 / 32, false)
@@ -104,7 +86,7 @@ fn signed_ovf_detect<'b, 'a: 'b, T: TargetRuntime<'a> + ?Sized>(
         "",
     );
 
-    let res = bin.builder.build_load(o, "mul");
+    let res = bin.builder.build_load(mul_ty, o, "mul");
     let ovf_any_type = if mul_bits != bits {
         // If there are any set bits, then there is an overflow.
         let check_ovf = bin.builder.build_right_shift(
@@ -222,31 +204,14 @@ fn call_mul32_without_ovf<'a>(
     o: PointerValue<'a>,
     mul_bits: u32,
     mul_type: IntType<'a>,
+    res_type: IntType<'a>,
 ) -> IntValue<'a> {
     bin.builder.build_call(
         bin.module.get_function("__mul32").unwrap(),
         &[
-            bin.builder
-                .build_pointer_cast(
-                    l,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "left",
-                )
-                .into(),
-            bin.builder
-                .build_pointer_cast(
-                    r,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "right",
-                )
-                .into(),
-            bin.builder
-                .build_pointer_cast(
-                    o,
-                    bin.context.i32_type().ptr_type(AddressSpace::default()),
-                    "output",
-                )
-                .into(),
+            l.into(),
+            r.into(),
+            o.into(),
             bin.context
                 .i32_type()
                 .const_int(mul_bits as u64 / 32, false)
@@ -255,10 +220,10 @@ fn call_mul32_without_ovf<'a>(
         "",
     );
 
-    let res = bin.builder.build_load(o, "mul");
+    let res = bin.builder.build_load(mul_type, o, "mul");
 
     bin.builder
-        .build_int_truncate(res.into_int_value(), mul_type, "")
+        .build_int_truncate(res.into_int_value(), res_type, "")
 }
 
 /// Utility function to extract the sign bit of an IntValue
@@ -333,27 +298,9 @@ pub(super) fn multiply<'a, T: TargetRuntime<'a> + ?Sized>(
             let return_val = bin.builder.build_call(
                 bin.module.get_function("__mul32_with_builtin_ovf").unwrap(),
                 &[
-                    bin.builder
-                        .build_pointer_cast(
-                            l,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "left",
-                        )
-                        .into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            r,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "right",
-                        )
-                        .into(),
-                    bin.builder
-                        .build_pointer_cast(
-                            o,
-                            bin.context.i32_type().ptr_type(AddressSpace::default()),
-                            "output",
-                        )
-                        .into(),
+                    l.into(),
+                    r.into(),
+                    o.into(),
                     bin.context
                         .i32_type()
                         .const_int(mul_bits as u64 / 32, false)
@@ -362,7 +309,7 @@ pub(super) fn multiply<'a, T: TargetRuntime<'a> + ?Sized>(
                 "ovf",
             );
 
-            let res = bin.builder.build_load(o, "mul");
+            let res = bin.builder.build_load(mul_ty, o, "mul");
 
             let error_block = bin.context.append_basic_block(function, "error");
             let return_block = bin.context.append_basic_block(function, "return_block");
@@ -426,7 +373,7 @@ pub(super) fn multiply<'a, T: TargetRuntime<'a> + ?Sized>(
             bin.builder
                 .build_int_truncate(res.into_int_value(), left.get_type(), "")
         } else {
-            return call_mul32_without_ovf(bin, l, r, o, mul_bits, left.get_type());
+            return call_mul32_without_ovf(bin, l, r, o, mul_bits, mul_ty, left.get_type());
         }
     } else if bin.options.math_overflow_check && !unchecked {
         build_binary_op_with_overflow_check(

+ 3 - 1
src/emit/mod.rs

@@ -8,7 +8,7 @@ use std::str;
 
 use crate::Target;
 use inkwell::targets::TargetTriple;
-use inkwell::types::IntType;
+use inkwell::types::{BasicTypeEnum, IntType};
 use inkwell::values::{
     ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
 };
@@ -159,6 +159,7 @@ pub trait TargetRuntime<'a> {
         function: FunctionValue,
         slot: PointerValue,
         dest: PointerValue,
+        dest_ty: BasicTypeEnum,
     );
 
     fn get_storage_extfunc(
@@ -269,6 +270,7 @@ pub trait TargetRuntime<'a> {
         function: FunctionValue<'a>,
         builtin_func: &Function,
         args: &[BasicMetadataValueEnum<'a>],
+        first_arg_type: BasicTypeEnum,
         ns: &Namespace,
     ) -> BasicValueEnum<'a>;
 

+ 139 - 153
src/emit/solana/mod.rs

@@ -222,8 +222,12 @@ impl SolanaTarget {
     fn contract_storage_account<'b>(&self, binary: &Binary<'b>) -> PointerValue<'b> {
         let parameters = self.sol_parameters(binary);
 
-        let account_info = unsafe {
+        unsafe {
             binary.builder.build_gep(
+                binary
+                    .module
+                    .get_struct_type("struct.SolParameters")
+                    .unwrap(),
                 parameters,
                 &[
                     binary.context.i32_type().const_int(0, false),
@@ -232,39 +236,20 @@ impl SolanaTarget {
                 ],
                 "account",
             )
-        };
-
-        binary.builder.build_pointer_cast(
-            account_info,
-            binary
-                .module
-                .get_struct_type("struct.SolAccountInfo")
-                .unwrap()
-                .ptr_type(AddressSpace::default()),
-            "account_info",
-        )
+        }
     }
 
     /// Get the pointer to SolParameters
     fn sol_parameters<'b>(&self, binary: &Binary<'b>) -> PointerValue<'b> {
-        let parameters = binary
+        binary
             .builder
             .get_insert_block()
             .unwrap()
             .get_parent()
             .unwrap()
             .get_last_param()
-            .unwrap();
-
-        binary.builder.build_pointer_cast(
-            parameters.into_pointer_value(),
-            binary
-                .module
-                .get_struct_type("struct.SolParameters")
-                .unwrap()
-                .ptr_type(AddressSpace::default()),
-            "parameters",
-        )
+            .unwrap()
+            .into_pointer_value()
     }
 
     /// Returns the account data of the executing binary
@@ -274,8 +259,13 @@ impl SolanaTarget {
         binary
             .builder
             .build_load(
+                binary.context.i8_type().ptr_type(AddressSpace::default()),
                 unsafe {
                     binary.builder.build_gep(
+                        binary
+                            .module
+                            .get_struct_type("struct.SolParameters")
+                            .unwrap(),
                         parameters,
                         &[
                             binary.context.i32_type().const_int(0, false),
@@ -308,18 +298,16 @@ impl SolanaTarget {
         }
 
         // the slot is simply the offset after the magic
-        let member = unsafe { binary.builder.build_gep(data, &[slot], "data") };
+        let member = unsafe {
+            binary
+                .builder
+                .build_gep(binary.context.i8_type(), data, &[slot], "data")
+        };
 
         if *ty == ast::Type::String || *ty == ast::Type::DynamicBytes {
-            let offset_ptr = binary.builder.build_pointer_cast(
-                member,
-                binary.context.i32_type().ptr_type(AddressSpace::default()),
-                "offset_ptr",
-            );
-
             let offset = binary
                 .builder
-                .build_load(offset_ptr, "offset")
+                .build_load(binary.context.i32_type(), member, "offset")
                 .into_int_value();
 
             binary.builder.build_call(
@@ -331,17 +319,10 @@ impl SolanaTarget {
             // account_data_alloc will return 0 if the string is length 0
             let new_offset = binary.context.i32_type().const_zero();
 
-            binary.builder.build_store(offset_ptr, new_offset);
+            binary.builder.build_store(member, new_offset);
         } else if let ast::Type::Array(elem_ty, dim) = ty {
             // delete the existing storage
             let mut elem_slot = slot;
-
-            let offset_ptr = binary.builder.build_pointer_cast(
-                member,
-                binary.context.i32_type().ptr_type(AddressSpace::default()),
-                "offset_ptr",
-            );
-
             let mut free_array = None;
 
             if elem_ty.is_dynamic(ns) || zero {
@@ -353,7 +334,7 @@ impl SolanaTarget {
                 } else {
                     elem_slot = binary
                         .builder
-                        .build_load(offset_ptr, "offset")
+                        .build_load(binary.context.i32_type(), member, "offset")
                         .into_int_value();
 
                     free_array = Some(elem_slot);
@@ -411,7 +392,7 @@ impl SolanaTarget {
                     // account_data_alloc will return 0 if the string is length 0
                     let new_offset = binary.context.i32_type().const_zero();
 
-                    binary.builder.build_store(offset_ptr, new_offset);
+                    binary.builder.build_store(member, new_offset);
                 }
             }
         } else if let ast::Type::Struct(struct_ty) = ty {
@@ -431,21 +412,15 @@ impl SolanaTarget {
         } else if matches!(ty, Type::Address(_) | Type::Contract(_)) {
             let ty = binary.llvm_type(ty, ns);
 
-            binary.builder.build_store(
-                binary
-                    .builder
-                    .build_pointer_cast(member, ty.ptr_type(AddressSpace::default()), ""),
-                ty.into_array_type().const_zero(),
-            );
+            binary
+                .builder
+                .build_store(member, ty.into_array_type().const_zero());
         } else {
             let ty = binary.llvm_type(ty, ns);
 
-            binary.builder.build_store(
-                binary
-                    .builder
-                    .build_pointer_cast(member, ty.ptr_type(AddressSpace::default()), ""),
-                ty.into_int_type().const_zero(),
-            );
+            binary
+                .builder
+                .build_store(member, ty.into_int_type().const_zero());
         }
     }
 
@@ -526,21 +501,23 @@ impl SolanaTarget {
             entry_ty
                 .ptr_type(AddressSpace::default())
                 .const_null()
-                .const_gep(&[
-                    binary.context.i32_type().const_zero(),
-                    binary.context.i32_type().const_int(2, false),
-                ])
+                .const_gep(
+                    entry_ty.as_basic_type_enum(),
+                    &[
+                        binary.context.i32_type().const_zero(),
+                        binary.context.i32_type().const_int(2, false),
+                    ],
+                )
                 .const_to_int(binary.context.i32_type())
         };
 
         let data = self.contract_storage_data(binary);
 
-        let member = unsafe { binary.builder.build_gep(data, &[offset], "data") };
-        let offset_ptr = binary.builder.build_pointer_cast(
-            member,
-            binary.context.i32_type().ptr_type(AddressSpace::default()),
-            "offset_ptr",
-        );
+        let member = unsafe {
+            binary
+                .builder
+                .build_gep(binary.context.i8_type(), data, &[offset], "data")
+        };
 
         let address = binary.build_alloca(function, binary.address_type(ns), "address");
 
@@ -564,14 +541,7 @@ impl SolanaTarget {
                 .builder
                 .build_call(
                     binary.module.get_function("address_hash").unwrap(),
-                    &[binary
-                        .builder
-                        .build_pointer_cast(
-                            address,
-                            binary.context.i8_type().ptr_type(AddressSpace::default()),
-                            "address_ptr",
-                        )
-                        .into()],
+                    &[address.into()],
                     "hash",
                 )
                 .try_as_basic_value()
@@ -597,7 +567,7 @@ impl SolanaTarget {
         let first_offset_ptr = unsafe {
             binary
                 .builder
-                .build_gep(offset_ptr, &[bucket], "bucket_list")
+                .build_gep(binary.context.i32_type(), member, &[bucket], "bucket_list")
         };
 
         // we should now loop until offset is zero or we found it
@@ -626,6 +596,7 @@ impl SolanaTarget {
         let offset = binary
             .builder
             .build_load(
+                binary.context.i32_type(),
                 offset_ptr_phi.as_basic_value().into_pointer_value(),
                 "offset",
             )
@@ -645,16 +616,16 @@ impl SolanaTarget {
         binary.builder.position_at_end(examine_bucket);
 
         // let's compare the key in this entry to the key we are looking for
-        let member = unsafe { binary.builder.build_gep(data, &[offset], "data") };
-        let entry_ptr = binary.builder.build_pointer_cast(
-            member,
-            entry_ty.ptr_type(AddressSpace::default()),
-            "offset_ptr",
-        );
+        let member = unsafe {
+            binary
+                .builder
+                .build_gep(binary.context.i8_type(), data, &[offset], "data")
+        };
 
         let ptr = unsafe {
             binary.builder.build_gep(
-                entry_ptr,
+                entry_ty,
+                member,
                 &[
                     binary.context.i32_type().const_zero(),
                     binary.context.i32_type().const_zero(),
@@ -664,13 +635,18 @@ impl SolanaTarget {
         };
 
         let matches = if matches!(key_ty, ast::Type::String | ast::Type::DynamicBytes) {
-            let entry_key = binary.builder.build_load(ptr, "key");
+            let entry_key = binary
+                .builder
+                .build_load(binary.context.i32_type(), ptr, "key");
 
             // entry_key is an offset
             let entry_data = unsafe {
-                binary
-                    .builder
-                    .build_gep(data, &[entry_key.into_int_value()], "data")
+                binary.builder.build_gep(
+                    binary.context.i8_type(),
+                    data,
+                    &[entry_key.into_int_value()],
+                    "data",
+                )
             };
             let entry_length = binary
                 .builder
@@ -705,24 +681,7 @@ impl SolanaTarget {
                 .builder
                 .build_call(
                     binary.module.get_function("address_equal").unwrap(),
-                    &[
-                        binary
-                            .builder
-                            .build_pointer_cast(
-                                address,
-                                binary.context.i8_type().ptr_type(AddressSpace::default()),
-                                "address_ptr",
-                            )
-                            .into(),
-                        binary
-                            .builder
-                            .build_pointer_cast(
-                                ptr,
-                                binary.context.i8_type().ptr_type(AddressSpace::default()),
-                                "offset_ptr",
-                            )
-                            .into(),
-                    ],
+                    &[address.into(), ptr.into()],
                     "",
                 )
                 .try_as_basic_value()
@@ -730,7 +689,9 @@ impl SolanaTarget {
                 .unwrap()
                 .into_int_value()
         } else {
-            let entry_key = binary.builder.build_load(ptr, "key");
+            let entry_key = binary
+                .builder
+                .build_load(binary.llvm_type(key_ty, ns), ptr, "key");
 
             binary.builder.build_int_compare(
                 IntPredicate::EQ,
@@ -763,7 +724,7 @@ impl SolanaTarget {
 
         let offset_ptr = binary
             .builder
-            .build_struct_gep(entry_ptr, 1, "offset_ptr")
+            .build_struct_gep(entry_ty, member, 1, "offset_ptr")
             .unwrap();
 
         offset_ptr_phi.add_incoming(&[(&offset_ptr, next_entry)]);
@@ -781,20 +742,12 @@ impl SolanaTarget {
 
         let account = self.contract_storage_account(binary);
 
-        let account_data_alloc = binary.module.get_function("account_data_alloc").unwrap();
-
-        let arg1 = binary.builder.build_pointer_cast(
-            account,
-            account_data_alloc.get_type().get_param_types()[0].into_pointer_type(),
-            "",
-        );
-
         // account_data_alloc will return offset = 0 if the string is length 0
         let rc = binary
             .builder
             .build_call(
                 binary.module.get_function("account_data_alloc").unwrap(),
-                &[arg1.into(), entry_length.into(), offset_ptr.into()],
+                &[account.into(), entry_length.into(), offset_ptr.into()],
                 "rc",
             )
             .try_as_basic_value()
@@ -824,10 +777,14 @@ impl SolanaTarget {
 
         let offset = binary
             .builder
-            .build_load(offset_ptr, "new_offset")
+            .build_load(binary.context.i32_type(), offset_ptr, "new_offset")
             .into_int_value();
 
-        let member = unsafe { binary.builder.build_gep(data, &[offset], "data") };
+        let member = unsafe {
+            binary
+                .builder
+                .build_gep(binary.context.i8_type(), data, &[offset], "data")
+        };
 
         // Clear memory. The length argument to __bzero8 is in lengths of 8 bytes. We round up to the nearest
         // 8 byte, since account_data_alloc also rounds up to the nearest 8 byte when allocating.
@@ -847,18 +804,12 @@ impl SolanaTarget {
             "zeroed",
         );
 
-        let entry_ptr = binary.builder.build_pointer_cast(
-            member,
-            entry_ty.ptr_type(AddressSpace::default()),
-            "offset_ptr",
-        );
-
         // set key
         if matches!(key_ty, ast::Type::String | ast::Type::DynamicBytes) {
             let new_string_length = binary.vector_len(key);
             let offset_ptr = binary
                 .builder
-                .build_struct_gep(entry_ptr, 0, "key_ptr")
+                .build_struct_gep(entry_ty, member, 0, "key_ptr")
                 .unwrap();
 
             // account_data_alloc will return offset = 0 if the string is length 0
@@ -898,7 +849,10 @@ impl SolanaTarget {
 
             binary.builder.position_at_end(rc_zero);
 
-            let new_offset = binary.builder.build_load(offset_ptr, "new_offset");
+            let new_offset =
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), offset_ptr, "new_offset");
 
             binary.builder.build_unconditional_branch(memcpy);
 
@@ -912,6 +866,7 @@ impl SolanaTarget {
 
             let dest_string_data = unsafe {
                 binary.builder.build_gep(
+                    binary.context.i8_type(),
                     data,
                     &[offset_phi.as_basic_value().into_int_value()],
                     "dest_string_data",
@@ -930,7 +885,7 @@ impl SolanaTarget {
         } else {
             let key_ptr = binary
                 .builder
-                .build_struct_gep(entry_ptr, 0, "key_ptr")
+                .build_struct_gep(entry_ty, member, 0, "key_ptr")
                 .unwrap();
 
             binary.builder.build_store(key_ptr, key);
@@ -1006,7 +961,10 @@ impl SolanaTarget {
 
         binary.builder.position_at_end(rc_zero);
 
-        binary.builder.build_load(offset, "offset").into_int_value()
+        binary
+            .builder
+            .build_load(binary.context.i32_type(), offset, "offset")
+            .into_int_value()
     }
 
     /// AccountInfo struct member
@@ -1018,34 +976,39 @@ impl SolanaTarget {
         member: usize,
         ns: &ast::Namespace,
     ) -> BasicValueEnum<'b> {
+        let account_info_ty = binary
+            .module
+            .get_struct_type("struct.SolAccountInfo")
+            .unwrap();
         match member {
             // key
             0 => {
                 let key = binary
                     .builder
                     .build_load(
+                        binary
+                            .module
+                            .get_struct_type("struct.SolPubkey")
+                            .unwrap()
+                            .ptr_type(AddressSpace::default()),
                         binary
                             .builder
-                            .build_struct_gep(account_info, 0, "key")
+                            .build_struct_gep(account_info_ty, account_info, 0, "key")
                             .unwrap(),
                         "key",
                     )
                     .into_pointer_value();
 
-                binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        key,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "address",
-                    ),
-                    "key",
-                )
+                binary
+                    .builder
+                    .build_load(binary.address_type(ns), key, "key")
             }
             // lamports
             1 => binary.builder.build_load(
+                binary.context.i64_type().ptr_type(AddressSpace::default()),
                 binary
                     .builder
-                    .build_struct_gep(account_info, 1, "lamports")
+                    .build_struct_gep(account_info_ty, account_info, 1, "lamports")
                     .unwrap(),
                 "lamports",
             ),
@@ -1054,18 +1017,20 @@ impl SolanaTarget {
                 let data_len = binary
                     .builder
                     .build_load(
+                        binary.context.i64_type(),
                         binary
                             .builder
-                            .build_struct_gep(account_info, 2, "data_len")
+                            .build_struct_gep(account_info_ty, account_info, 2, "data_len")
                             .unwrap(),
                         "data_len",
                     )
                     .into_int_value();
 
                 let data = binary.builder.build_load(
+                    binary.context.i8_type().ptr_type(AddressSpace::default()),
                     binary
                         .builder
-                        .build_struct_gep(account_info, 3, "data")
+                        .build_struct_gep(account_info_ty, account_info, 3, "data")
                         .unwrap(),
                     "data",
                 );
@@ -1077,58 +1042,79 @@ impl SolanaTarget {
                 );
                 let data_elem = binary
                     .builder
-                    .build_struct_gep(slice_alloca, 0, "data")
+                    .build_struct_gep(
+                        binary.llvm_type(&ast::Type::Slice(Box::new(Type::Bytes(1))), ns),
+                        slice_alloca,
+                        0,
+                        "data",
+                    )
                     .unwrap();
                 binary.builder.build_store(data_elem, data);
                 let data_len_elem = binary
                     .builder
-                    .build_struct_gep(slice_alloca, 1, "data_len")
+                    .build_struct_gep(
+                        binary.llvm_type(&ast::Type::Slice(Box::new(Type::Bytes(1))), ns),
+                        slice_alloca,
+                        1,
+                        "data_len",
+                    )
                     .unwrap();
                 binary.builder.build_store(data_len_elem, data_len);
 
-                binary.builder.build_load(slice_alloca, "data_slice")
+                binary.builder.build_load(
+                    binary.llvm_type(&ast::Type::Slice(Box::new(Type::Bytes(1))), ns),
+                    slice_alloca,
+                    "data_slice",
+                )
             }
             // owner
             3 => {
                 let owner = binary
                     .builder
                     .build_load(
+                        binary
+                            .module
+                            .get_struct_type("struct.SolPubkey")
+                            .unwrap()
+                            .ptr_type(AddressSpace::default()),
                         binary
                             .builder
-                            .build_struct_gep(account_info, 4, "owner")
+                            .build_struct_gep(account_info_ty, account_info, 4, "owner")
                             .unwrap(),
                         "owner",
                     )
                     .into_pointer_value();
 
-                binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        owner,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "address",
-                    ),
-                    "owner",
-                )
+                binary
+                    .builder
+                    .build_load(binary.address_type(ns), owner, "owner")
             }
             // rent epoch
             4 => {
                 let rent_epoch = binary
                     .builder
-                    .build_struct_gep(account_info, 5, "rent_epoch")
+                    .build_struct_gep(account_info_ty, account_info, 5, "rent_epoch")
                     .unwrap();
 
-                binary.builder.build_load(rent_epoch, "rent_epoch")
+                binary
+                    .builder
+                    .build_load(binary.context.i64_type(), rent_epoch, "rent_epoch")
             }
             // remaining fields are bool
             _ => {
                 let bool_field = binary
                     .builder
-                    .build_struct_gep(account_info, member as u32 + 1, "bool_field")
+                    .build_struct_gep(
+                        account_info_ty,
+                        account_info,
+                        member as u32 + 1,
+                        "bool_field",
+                    )
                     .unwrap();
 
                 let value = binary
                     .builder
-                    .build_load(bool_field, "bool_field")
+                    .build_load(binary.context.i8_type(), bool_field, "bool_field")
                     .into_int_value();
 
                 binary

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 226 - 306
src/emit/solana/target.rs


+ 8 - 1
src/emit/storage.rs

@@ -2,11 +2,18 @@
 
 use crate::emit::binary::Binary;
 use crate::sema::ast::{Namespace, Type};
+use inkwell::types::BasicTypeEnum;
 use inkwell::values::{ArrayValue, BasicValueEnum, FunctionValue, IntValue, PointerValue};
 
 /// This trait species the methods for managing storage on slot based environments
 pub(super) trait StorageSlot {
-    fn set_storage(&self, binary: &Binary, slot: PointerValue, dest: PointerValue);
+    fn set_storage(
+        &self,
+        binary: &Binary,
+        slot: PointerValue,
+        dest: PointerValue,
+        dest_ty: BasicTypeEnum,
+    );
 
     fn get_storage_address<'a>(
         &self,

+ 34 - 36
src/emit/strings.rs

@@ -6,7 +6,7 @@ use crate::emit::expression::expression;
 use crate::emit::{TargetRuntime, Variable};
 use crate::sema::ast::{FormatArg, Namespace, RetrieveType, StringLocation, Type};
 use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
-use inkwell::{AddressSpace, IntPredicate};
+use inkwell::IntPredicate;
 use std::collections::HashMap;
 
 /// Implement "...{}...{}".format(a, b)
@@ -110,7 +110,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                     "",
                 );
 
-                output = unsafe { bin.builder.build_gep(output, &[len], "") };
+                output = unsafe {
+                    bin.builder
+                        .build_gep(bin.context.i8_type(), output, &[len], "")
+                };
             }
         } else {
             let val = evaluated_arg[i]
@@ -142,7 +145,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                         "",
                     );
 
-                    output = unsafe { bin.builder.build_gep(output, &[len], "") };
+                    output = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[len], "")
+                    };
                 }
                 Type::String => {
                     let s = bin.vector_bytes(val);
@@ -154,7 +160,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                         "",
                     );
 
-                    output = unsafe { bin.builder.build_gep(output, &[len], "") };
+                    output = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[len], "")
+                    };
                 }
                 Type::DynamicBytes => {
                     let s = bin.vector_bytes(val);
@@ -168,7 +177,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
 
                     let hex_len = bin.builder.build_int_add(len, len, "hex_len");
 
-                    output = unsafe { bin.builder.build_gep(output, &[hex_len], "") };
+                    output = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[hex_len], "")
+                    };
                 }
                 Type::Address(_) | Type::Contract(_) => {
                     // for Solana/Substrate, we should encode in base58
@@ -181,21 +193,18 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                         .i32_type()
                         .const_int(ns.address_length as u64, false);
 
-                    let s = bin.builder.build_pointer_cast(
-                        buf,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "address_bytes",
-                    );
-
                     bin.builder.build_call(
                         bin.module.get_function("hex_encode").unwrap(),
-                        &[output.into(), s.into(), len.into()],
+                        &[output.into(), buf.into(), len.into()],
                         "",
                     );
 
                     let hex_len = bin.builder.build_int_add(len, len, "hex_len");
 
-                    output = unsafe { bin.builder.build_gep(output, &[hex_len], "") };
+                    output = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[hex_len], "")
+                    };
                 }
                 Type::Bytes(size) => {
                     let buf = bin.build_alloca(function, bin.llvm_type(&arg_ty, ns), "bytesN");
@@ -204,21 +213,18 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
 
                     let len = bin.context.i32_type().const_int(size as u64, false);
 
-                    let s = bin.builder.build_pointer_cast(
-                        buf,
-                        bin.context.i8_type().ptr_type(AddressSpace::default()),
-                        "bytes",
-                    );
-
                     bin.builder.build_call(
                         bin.module.get_function("hex_encode_rev").unwrap(),
-                        &[output.into(), s.into(), len.into()],
+                        &[output.into(), buf.into(), len.into()],
                         "",
                     );
 
                     let hex_len = bin.builder.build_int_add(len, len, "hex_len");
 
-                    output = unsafe { bin.builder.build_gep(output, &[hex_len], "") };
+                    output = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[hex_len], "")
+                    };
                 }
                 Type::Enum(_) => {
                     let val = bin.builder.build_int_z_extend(
@@ -319,12 +325,6 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
 
                         bin.builder.build_store(buf, val.into_int_value());
 
-                        let s = bin.builder.build_pointer_cast(
-                            buf,
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "uint",
-                        );
-
                         let len = bin.context.i32_type().const_int(bits as u64 / 8, false);
 
                         let func_name = if *spec == FormatArg::Hex {
@@ -337,7 +337,7 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                             .builder
                             .build_call(
                                 bin.module.get_function(func_name).unwrap(),
-                                &[output.into(), s.into(), len.into()],
+                                &[output.into(), buf.into(), len.into()],
                                 "",
                             )
                             .try_as_basic_value()
@@ -371,7 +371,10 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
 
                     let minus_len = bin.context.i32_type().const_int(1, false);
 
-                    let neg_data = unsafe { bin.builder.build_gep(output, &[minus_len], "") };
+                    let neg_data = unsafe {
+                        bin.builder
+                            .build_gep(bin.context.i8_type(), output, &[minus_len], "")
+                    };
                     let neg_val = bin.builder.build_int_neg(val, "negative_int");
 
                     bin.builder.build_unconditional_branch(positive);
@@ -470,12 +473,6 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                         bin.builder
                             .build_store(buf, val_phi.as_basic_value().into_int_value());
 
-                        let s = bin.builder.build_pointer_cast(
-                            buf,
-                            bin.context.i8_type().ptr_type(AddressSpace::default()),
-                            "int",
-                        );
-
                         let len = bin.context.i32_type().const_int(bits as u64 / 8, false);
 
                         let func_name = if *spec == FormatArg::Hex {
@@ -490,7 +487,7 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
                             .builder
                             .build_call(
                                 bin.module.get_function(func_name).unwrap(),
-                                &[output_after_minus.into(), s.into(), len.into()],
+                                &[output_after_minus.into(), buf.into(), len.into()],
                                 "",
                             )
                             .try_as_basic_value()
@@ -515,6 +512,7 @@ pub(super) fn format_string<'a, T: TargetRuntime<'a> + ?Sized>(
 
     let data_len = unsafe {
         bin.builder.build_gep(
+            bin.module.get_struct_type("struct.vector").unwrap(),
             vector,
             &[
                 bin.context.i32_type().const_zero(),

+ 2 - 1
src/emit/substrate/dispatch.rs

@@ -57,7 +57,7 @@ impl SubstrateTarget {
 
         let fid = bin
             .builder
-            .build_load(argsdata, "function_selector")
+            .build_load(bin.context.i32_type(), argsdata, "function_selector")
             .into_int_value();
 
         // TODO: solana does not support bss, so different solution is needed
@@ -67,6 +67,7 @@ impl SubstrateTarget {
         // step over the function selector
         let argsdata = unsafe {
             bin.builder.build_gep(
+                bin.context.i32_type(),
                 argsdata,
                 &[bin.context.i32_type().const_int(1, false)],
                 "argsdata",

+ 137 - 159
src/emit/substrate/mod.rs

@@ -45,18 +45,6 @@ macro_rules! emit_context {
             };
         }
 
-        #[allow(unused_macros)]
-        macro_rules! cast_byte_ptr {
-            ($val:expr) => {
-                $binary.builder.build_pointer_cast($val, byte_ptr!(), "")
-            };
-            ($val:expr, $ptr_name:literal) => {
-                $binary
-                    .builder
-                    .build_pointer_cast($val, byte_ptr!(), $ptr_name)
-            };
-        }
-
         #[allow(unused_macros)]
         macro_rules! call {
             ($name:expr, $args:expr) => {
@@ -105,11 +93,7 @@ macro_rules! emit_context {
         macro_rules! scratch_buf {
             () => {
                 (
-                    $binary.builder.build_pointer_cast(
-                        $binary.scratch.unwrap().as_pointer_value(),
-                        $binary.context.i8_type().ptr_type(AddressSpace::default()),
-                        "scratch_buf",
-                    ),
+                    $binary.scratch.unwrap().as_pointer_value(),
                     $binary.scratch_len.unwrap().as_pointer_value(),
                 )
             };
@@ -228,11 +212,7 @@ impl SubstrateTarget {
             .builder
             .build_call(binary.module.get_function("__init_heap").unwrap(), &[], "");
 
-        let scratch_buf = binary.builder.build_pointer_cast(
-            binary.scratch.unwrap().as_pointer_value(),
-            binary.context.i8_type().ptr_type(AddressSpace::default()),
-            "scratch_buf",
-        );
+        let scratch_buf = binary.scratch.unwrap().as_pointer_value();
         let scratch_len = binary.scratch_len.unwrap().as_pointer_value();
 
         // copy arguments from input buffer
@@ -250,12 +230,10 @@ impl SubstrateTarget {
             "",
         );
 
-        let args = binary.builder.build_pointer_cast(
-            scratch_buf,
-            binary.context.i32_type().ptr_type(AddressSpace::default()),
-            "",
-        );
-        let args_length = binary.builder.build_load(scratch_len, "input_len");
+        let args_length =
+            binary
+                .builder
+                .build_load(binary.context.i32_type(), scratch_len, "input_len");
 
         // store the length in case someone wants it via msg.data
         binary.builder.build_store(
@@ -263,7 +241,7 @@ impl SubstrateTarget {
             args_length.into_int_value(),
         );
 
-        (args, args_length.into_int_value())
+        (scratch_buf, args_length.into_int_value())
     }
 
     fn declare_externals(&self, binary: &Binary) {
@@ -444,7 +422,10 @@ impl SubstrateTarget {
             ast::Type::Bool => {
                 let val = binary.builder.build_int_compare(
                     IntPredicate::EQ,
-                    binary.builder.build_load(src, "abi_bool").into_int_value(),
+                    binary
+                        .builder
+                        .build_load(binary.context.i8_type(), src, "abi_bool")
+                        .into_int_value(),
                     binary.context.i8_type().const_int(1, false),
                     "bool",
                 );
@@ -453,14 +434,7 @@ impl SubstrateTarget {
             ast::Type::Uint(bits) | ast::Type::Int(bits) => {
                 let int_type = binary.context.custom_width_int_type(*bits as u32);
 
-                let val = binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        src,
-                        int_type.ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    "",
-                );
+                let val = binary.builder.build_load(int_type, src, "");
 
                 // substrate only supports power-of-two types; step over the
                 // the remainer
@@ -472,14 +446,7 @@ impl SubstrateTarget {
                 (val, len)
             }
             ast::Type::Contract(_) | ast::Type::Address(_) => {
-                let val = binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        src,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    "",
-                );
+                let val = binary.builder.build_load(binary.address_type(ns), src, "");
 
                 let len = ns.address_length as u64;
 
@@ -495,14 +462,7 @@ impl SubstrateTarget {
                     binary.module.get_function("__beNtoleN").unwrap(),
                     &[
                         src.into(),
-                        binary
-                            .builder
-                            .build_pointer_cast(
-                                buf,
-                                binary.context.i8_type().ptr_type(AddressSpace::default()),
-                                "",
-                            )
-                            .into(),
+                        buf.into(),
                         binary
                             .context
                             .i32_type()
@@ -513,7 +473,9 @@ impl SubstrateTarget {
                 );
 
                 (
-                    binary.builder.build_load(buf, &format!("bytes{len}")),
+                    binary
+                        .builder
+                        .build_load(int_type, buf, &format!("bytes{len}")),
                     *len as u64,
                 )
             }
@@ -588,6 +550,7 @@ impl SubstrateTarget {
 
                 *data = unsafe {
                     binary.builder.build_gep(
+                        binary.context.i8_type(),
                         *data,
                         &[binary.context.i32_type().const_int(arglen, false)],
                         "abi_ptr",
@@ -622,16 +585,11 @@ impl SubstrateTarget {
                     .unwrap()
                     .into_pointer_value();
 
-                let dest = binary.builder.build_pointer_cast(
-                    new,
-                    llvm_ty.ptr_type(AddressSpace::default()),
-                    "dest",
-                );
-
                 for (i, field) in str_ty.definition(ns).fields.iter().enumerate() {
                     let elem = unsafe {
                         binary.builder.build_gep(
-                            dest,
+                            llvm_ty,
+                            new,
                             &[
                                 binary.context.i32_type().const_zero(),
                                 binary.context.i32_type().const_int(i as u64, false),
@@ -642,10 +600,13 @@ impl SubstrateTarget {
 
                     let val = self.decode_ty(binary, function, &field.ty, data, end, ns);
 
-                    let val = if field.ty.deref_memory().is_fixed_reference_type() {
-                        binary
-                            .builder
-                            .build_load(val.into_pointer_value(), field.name_as_str())
+                    let val = if field.ty.deref_memory().is_fixed_reference_type(ns) {
+                        let field_ty = binary.llvm_type(&field.ty, ns);
+                        binary.builder.build_load(
+                            field_ty,
+                            val.into_pointer_value(),
+                            field.name_as_str(),
+                        )
                     } else {
                         val
                     };
@@ -653,7 +614,7 @@ impl SubstrateTarget {
                     binary.builder.build_store(elem, val);
                 }
 
-                dest.into()
+                new.into()
             }
             ast::Type::Array(_, dim) => {
                 if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
@@ -678,12 +639,6 @@ impl SubstrateTarget {
                         .unwrap()
                         .into_pointer_value();
 
-                    let dest = binary.builder.build_pointer_cast(
-                        new,
-                        llvm_ty.ptr_type(AddressSpace::default()),
-                        "dest",
-                    );
-
                     binary.emit_static_loop_with_pointer(
                         function,
                         binary.context.i64_type().const_zero(),
@@ -695,7 +650,8 @@ impl SubstrateTarget {
                         |index: IntValue<'b>, data: &mut PointerValue<'b>| {
                             let elem = unsafe {
                                 binary.builder.build_gep(
-                                    dest,
+                                    llvm_ty,
+                                    new,
                                     &[binary.context.i32_type().const_zero(), index],
                                     "index_access",
                                 )
@@ -703,8 +659,13 @@ impl SubstrateTarget {
 
                             let val = self.decode_ty(binary, function, &ty, data, end, ns);
 
-                            let val = if ty.deref_memory().is_fixed_reference_type() {
-                                binary.builder.build_load(val.into_pointer_value(), "elem")
+                            let val = if ty.deref_memory().is_fixed_reference_type(ns) {
+                                let field_ty = binary.llvm_type(ty.deref_memory(), ns);
+                                binary.builder.build_load(
+                                    field_ty,
+                                    val.into_pointer_value(),
+                                    "elem",
+                                )
                             } else {
                                 val
                             };
@@ -713,7 +674,7 @@ impl SubstrateTarget {
                         },
                     );
 
-                    dest.into()
+                    new.into()
                 } else {
                     let len = binary
                         .builder
@@ -731,7 +692,10 @@ impl SubstrateTarget {
                         .unwrap()
                         .into_pointer_value();
 
-                    let len = binary.builder.build_load(len, "array.len").into_int_value();
+                    let len = binary
+                        .builder
+                        .build_load(binary.context.i32_type(), len, "array.len")
+                        .into_int_value();
 
                     // details about our array elements
                     let elem_ty = binary.llvm_field_ty(&ty.array_elem(), ns);
@@ -768,6 +732,7 @@ impl SubstrateTarget {
 
                             let element_start = unsafe {
                                 binary.builder.build_gep(
+                                    binary.context.get_struct_type("struct.vector").unwrap(),
                                     v,
                                     &[
                                         binary.context.i32_type().const_zero(),
@@ -778,23 +743,20 @@ impl SubstrateTarget {
                                 )
                             };
 
-                            let elem = binary.builder.build_pointer_cast(
-                                element_start,
-                                elem_ty.ptr_type(AddressSpace::default()),
-                                "entry",
-                            );
-
                             let ty = ty.array_deref();
 
                             let val = self.decode_ty(binary, function, &ty, data, end, ns);
 
-                            let val = if ty.deref_memory().is_fixed_reference_type() {
-                                binary.builder.build_load(val.into_pointer_value(), "elem")
+                            let val = if ty.deref_memory().is_fixed_reference_type(ns) {
+                                let load_ty = binary.llvm_type(ty.deref_memory(), ns);
+                                binary
+                                    .builder
+                                    .build_load(load_ty, val.into_pointer_value(), "elem")
                             } else {
                                 val
                             };
 
-                            binary.builder.build_store(elem, val);
+                            binary.builder.build_store(element_start, val);
                         },
                     );
                     v.into()
@@ -819,7 +781,14 @@ impl SubstrateTarget {
                     .left()
                     .unwrap();
 
-                *data = binary.builder.build_load(from, "data").into_pointer_value();
+                *data = binary
+                    .builder
+                    .build_load(
+                        binary.context.i8_type().ptr_type(AddressSpace::default()),
+                        from,
+                        "data",
+                    )
+                    .into_pointer_value();
 
                 self.check_overrun(binary, function, *data, end, false);
 
@@ -849,14 +818,9 @@ impl SubstrateTarget {
                     .unwrap()
                     .into_pointer_value();
 
-                let ef = binary.builder.build_pointer_cast(
-                    ef,
-                    ty.ptr_type(AddressSpace::default()),
-                    "function_type",
-                );
-
                 let address_member = unsafe {
                     binary.builder.build_gep(
+                        ty,
                         ef,
                         &[
                             binary.context.i32_type().const_zero(),
@@ -870,6 +834,7 @@ impl SubstrateTarget {
 
                 let selector_member = unsafe {
                     binary.builder.build_gep(
+                        ty,
                         ef,
                         &[
                             binary.context.i32_type().const_zero(),
@@ -900,7 +865,10 @@ impl SubstrateTarget {
         match ty {
             ast::Type::Bool => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns);
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -923,7 +891,10 @@ impl SubstrateTarget {
                 };
 
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns);
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -951,32 +922,20 @@ impl SubstrateTarget {
                     )
                 };
 
-                binary.builder.build_store(
-                    binary.builder.build_pointer_cast(
-                        dest,
-                        arg.get_type().ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    arg,
-                );
+                binary.builder.build_store(dest, arg);
 
                 power_of_two_len
             }
             ast::Type::Contract(_) | ast::Type::Address(_) => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    binary
+                        .builder
+                        .build_load(binary.address_type(ns), arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
 
-                binary.builder.build_store(
-                    binary.builder.build_pointer_cast(
-                        dest,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    arg.into_array_value(),
-                );
+                binary.builder.build_store(dest, arg.into_array_value());
 
                 ns.address_length as u64
             }
@@ -997,14 +956,7 @@ impl SubstrateTarget {
                 binary.builder.build_call(
                     binary.module.get_function("__leNtobeN").unwrap(),
                     &[
-                        binary
-                            .builder
-                            .build_pointer_cast(
-                                val,
-                                binary.context.i8_type().ptr_type(AddressSpace::default()),
-                                "",
-                            )
-                            .into(),
+                        val.into(),
                         dest.into(),
                         binary.context.i32_type().const_int(*n as u64, false).into(),
                     ],
@@ -1045,6 +997,7 @@ impl SubstrateTarget {
 
                 *data = unsafe {
                     binary.builder.build_gep(
+                        binary.context.i8_type(),
                         *data,
                         &[binary.context.i32_type().const_int(arglen, false)],
                         "",
@@ -1073,9 +1026,10 @@ impl SubstrateTarget {
             ),
             ast::Type::Array(_, dim) if matches!(dim.last(), Some(ast::ArrayLength::Fixed(_))) => {
                 let arg = if load {
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
                     binary
                         .builder
-                        .build_load(arg.into_pointer_value(), "")
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                         .into_pointer_value()
                 } else {
                     arg.into_pointer_value()
@@ -1107,6 +1061,7 @@ impl SubstrateTarget {
                     |index, elem_data| {
                         let elem = unsafe {
                             binary.builder.build_gep(
+                                binary.llvm_type(ty, ns),
                                 arg,
                                 &[binary.context.i32_type().const_zero(), index],
                                 "index_access",
@@ -1116,7 +1071,7 @@ impl SubstrateTarget {
                         self.encode_ty(
                             binary,
                             ns,
-                            !elem_ty.is_fixed_reference_type(),
+                            !elem_ty.is_fixed_reference_type(ns),
                             packed,
                             function,
                             &elem_ty,
@@ -1172,7 +1127,10 @@ impl SubstrateTarget {
             }
             ast::Type::Array(..) => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -1207,7 +1165,7 @@ impl SubstrateTarget {
                         self.encode_ty(
                             binary,
                             ns,
-                            !elem_ty.deref_any().is_fixed_reference_type(),
+                            !elem_ty.deref_any().is_fixed_reference_type(ns),
                             packed,
                             function,
                             elem_ty.deref_any(),
@@ -1219,9 +1177,11 @@ impl SubstrateTarget {
             }
             ast::Type::Struct(str_ty) => {
                 let arg = if load {
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
                     binary
                         .builder
                         .build_load(
+                            load_ty,
                             arg.into_pointer_value(),
                             &format!("encode_{}", str_ty.definition(ns).name),
                         )
@@ -1246,6 +1206,7 @@ impl SubstrateTarget {
                 for (i, field) in str_ty.definition(ns).fields.iter().enumerate() {
                     let elem = unsafe {
                         binary.builder.build_gep(
+                            binary.llvm_type(ty, ns),
                             arg,
                             &[
                                 binary.context.i32_type().const_zero(),
@@ -1258,7 +1219,7 @@ impl SubstrateTarget {
                     self.encode_ty(
                         binary,
                         ns,
-                        !field.ty.is_fixed_reference_type(),
+                        !field.ty.is_fixed_reference_type(ns),
                         packed,
                         function,
                         &field.ty,
@@ -1310,7 +1271,7 @@ impl SubstrateTarget {
                 self.encode_ty(
                     binary,
                     ns,
-                    !ty.is_fixed_reference_type(),
+                    !ty.is_fixed_reference_type(ns),
                     packed,
                     function,
                     ty,
@@ -1320,7 +1281,10 @@ impl SubstrateTarget {
             }
             ast::Type::String | ast::Type::DynamicBytes => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -1346,33 +1310,30 @@ impl SubstrateTarget {
                 } else {
                     binary.builder.build_call(
                         binary.module.get_function("__memcpy").unwrap(),
-                        &[
-                            (*data).into(),
-                            binary
-                                .builder
-                                .build_pointer_cast(
-                                    string_data,
-                                    binary.context.i8_type().ptr_type(AddressSpace::default()),
-                                    "",
-                                )
-                                .into(),
-                            string_len.into(),
-                        ],
+                        &[(*data).into(), string_data.into(), string_len.into()],
                         "",
                     );
 
-                    *data = unsafe { binary.builder.build_gep(*data, &[string_len], "") };
+                    *data = unsafe {
+                        binary
+                            .builder
+                            .build_gep(binary.context.i8_type(), *data, &[string_len], "")
+                    };
                 }
             }
             ast::Type::ExternalFunction { .. } => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
 
                 let address_member = unsafe {
                     binary.builder.build_gep(
+                        binary.llvm_type(ty, ns),
                         arg.into_pointer_value(),
                         &[
                             binary.context.i32_type().const_zero(),
@@ -1382,7 +1343,10 @@ impl SubstrateTarget {
                     )
                 };
 
-                let address = binary.builder.build_load(address_member, "address");
+                let address =
+                    binary
+                        .builder
+                        .build_load(binary.address_type(ns), address_member, "address");
 
                 self.encode_ty(
                     binary,
@@ -1397,6 +1361,7 @@ impl SubstrateTarget {
 
                 let selector_member = unsafe {
                     binary.builder.build_gep(
+                        binary.llvm_type(ty, ns),
                         arg.into_pointer_value(),
                         &[
                             binary.context.i32_type().const_zero(),
@@ -1406,7 +1371,11 @@ impl SubstrateTarget {
                     )
                 };
 
-                let selector = binary.builder.build_load(selector_member, "selector");
+                let selector = binary.builder.build_load(
+                    binary.context.i32_type(),
+                    selector_member,
+                    "selector",
+                );
 
                 self.encode_ty(
                     binary,
@@ -1475,9 +1444,11 @@ impl SubstrateTarget {
             ),
             ast::Type::Struct(str_ty) => {
                 let arg = if load {
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
                     binary
                         .builder
                         .build_load(
+                            load_ty,
                             arg.into_pointer_value(),
                             &format!("encoded_length_struct_{}", str_ty.definition(ns).name),
                         )
@@ -1504,6 +1475,7 @@ impl SubstrateTarget {
                 for (i, field) in str_ty.definition(ns).fields.iter().enumerate() {
                     let elem = unsafe {
                         binary.builder.build_gep(
+                            binary.llvm_type(ty, ns),
                             arg,
                             &[
                                 binary.context.i32_type().const_zero(),
@@ -1517,7 +1489,7 @@ impl SubstrateTarget {
                         normal_sum,
                         SubstrateTarget::encoded_length(
                             elem.into(),
-                            !field.ty.is_fixed_reference_type(),
+                            !field.ty.is_fixed_reference_type(ns),
                             packed,
                             &field.ty,
                             function,
@@ -1576,9 +1548,10 @@ impl SubstrateTarget {
 
                 if elem_ty.is_dynamic(ns) {
                     let arg = if load {
+                        let load_ty = binary.llvm_var_ty(ty, ns);
                         binary
                             .builder
-                            .build_load(arg.into_pointer_value(), "")
+                            .build_load(load_ty, arg.into_pointer_value(), "")
                             .into_pointer_value()
                     } else {
                         arg.into_pointer_value()
@@ -1608,6 +1581,7 @@ impl SubstrateTarget {
                         |index, sum| {
                             let elem = unsafe {
                                 binary.builder.build_gep(
+                                    binary.llvm_type(ty, ns),
                                     arg,
                                     &[binary.context.i32_type().const_zero(), index],
                                     "index_access",
@@ -1617,7 +1591,7 @@ impl SubstrateTarget {
                             *sum = binary.builder.build_int_add(
                                 SubstrateTarget::encoded_length(
                                     elem.into(),
-                                    !elem_ty.deref_memory().is_fixed_reference_type(),
+                                    !elem_ty.deref_memory().is_fixed_reference_type(ns),
                                     packed,
                                     &elem_ty,
                                     function,
@@ -1689,7 +1663,10 @@ impl SubstrateTarget {
             }
             ast::Type::Array(_, dims) if dims.last() == Some(&ast::ArrayLength::Dynamic) => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -1712,8 +1689,6 @@ impl SubstrateTarget {
                             let index = binary.builder.build_int_mul(
                                 index,
                                 llvm_elem_ty
-                                    .into_pointer_type()
-                                    .get_element_type()
                                     .size_of()
                                     .unwrap()
                                     .const_cast(binary.context.i32_type(), false),
@@ -1722,6 +1697,7 @@ impl SubstrateTarget {
 
                             let p = unsafe {
                                 binary.builder.build_gep(
+                                    binary.llvm_type(ty, ns),
                                     arg.into_pointer_value(),
                                     &[
                                         binary.context.i32_type().const_zero(),
@@ -1731,16 +1707,11 @@ impl SubstrateTarget {
                                     "index_access",
                                 )
                             };
-                            let elem = binary.builder.build_pointer_cast(
-                                p,
-                                llvm_elem_ty.into_pointer_type(),
-                                "elem",
-                            );
 
                             *sum = binary.builder.build_int_add(
                                 SubstrateTarget::encoded_length(
-                                    elem.into(),
-                                    !elem_ty.deref_memory().is_fixed_reference_type(),
+                                    p.into(),
+                                    !elem_ty.deref_memory().is_fixed_reference_type(ns),
                                     packed,
                                     &elem_ty,
                                     function,
@@ -1782,7 +1753,10 @@ impl SubstrateTarget {
             }
             ast::Type::String | ast::Type::DynamicBytes => {
                 let arg = if load {
-                    binary.builder.build_load(arg.into_pointer_value(), "")
+                    let load_ty = binary.llvm_type(ty, ns).ptr_type(AddressSpace::default());
+                    binary
+                        .builder
+                        .build_load(load_ty, arg.into_pointer_value(), "")
                 } else {
                     arg
                 };
@@ -1885,7 +1859,11 @@ fn log_return_code(binary: &Binary, api: &'static str, code: IntValue) {
         "__memcpy",
         &[out_buf_offset.into(), msg_string.into(), msg_len.into()]
     );
-    out_buf_offset = unsafe { binary.builder.build_gep(out_buf_offset, &[msg_len], "") };
+    out_buf_offset = unsafe {
+        binary
+            .builder
+            .build_gep(binary.context.i8_type(), out_buf_offset, &[msg_len], "")
+    };
 
     let code = binary
         .builder

+ 99 - 71
src/emit/substrate/storage.rs

@@ -6,19 +6,22 @@ use crate::emit::substrate::{log_return_code, SubstrateTarget};
 use crate::emit::TargetRuntime;
 use crate::emit_context;
 use crate::sema::ast::{ArrayLength, Namespace, Type};
-use inkwell::types::BasicType;
+use inkwell::types::{BasicType, BasicTypeEnum};
 use inkwell::values::{ArrayValue, BasicValueEnum, FunctionValue, IntValue, PointerValue};
 use inkwell::{AddressSpace, IntPredicate};
 use num_bigint::BigInt;
 use num_traits::{One, ToPrimitive};
 
 impl StorageSlot for SubstrateTarget {
-    fn set_storage(&self, binary: &Binary, slot: PointerValue, dest: PointerValue) {
+    fn set_storage(
+        &self,
+        binary: &Binary,
+        slot: PointerValue,
+        dest: PointerValue,
+        dest_ty: BasicTypeEnum,
+    ) {
         emit_context!(binary);
 
-        // TODO: check for non-zero
-        let dest_ty = dest.get_type().get_element_type();
-
         let dest_size = if dest_ty.is_array_type() {
             dest_ty
                 .into_array_type()
@@ -33,9 +36,9 @@ impl StorageSlot for SubstrateTarget {
         };
 
         let ret = seal_set_storage!(
-            cast_byte_ptr!(slot).into(),
+            slot.into(),
             i32_const!(32).into(),
-            cast_byte_ptr!(dest).into(),
+            dest.into(),
             dest_size.into()
         );
 
@@ -57,7 +60,7 @@ impl StorageSlot for SubstrateTarget {
             .build_store(scratch_len, i32_const!(ns.address_length as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot).into(),
+            slot.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -78,14 +81,7 @@ impl StorageSlot for SubstrateTarget {
                 exists,
                 binary
                     .builder
-                    .build_load(
-                        binary.builder.build_pointer_cast(
-                            scratch_buf,
-                            binary.address_type(ns).ptr_type(AddressSpace::default()),
-                            "address_ptr",
-                        ),
-                        "address",
-                    )
+                    .build_load(binary.address_type(ns), scratch_buf, "address")
                     .into_array_value(),
                 binary.address_type(ns).const_zero(),
                 "retrieved_address",
@@ -96,14 +92,11 @@ impl StorageSlot for SubstrateTarget {
     fn storage_delete_single_slot(&self, binary: &Binary, slot: PointerValue) {
         emit_context!(binary);
 
-        let ret = call!(
-            "seal_clear_storage",
-            &[cast_byte_ptr!(slot).into(), i32_const!(32).into()]
-        )
-        .try_as_basic_value()
-        .left()
-        .unwrap()
-        .into_int_value();
+        let ret = call!("seal_clear_storage", &[slot.into(), i32_const!(32).into()])
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_int_value();
 
         log_return_code(binary, "seal_clear_storage", ret);
     }
@@ -138,12 +131,6 @@ impl StorageSlot for SubstrateTarget {
                         .unwrap()
                         .into_pointer_value();
 
-                    let dest = bin.builder.build_pointer_cast(
-                        new,
-                        llvm_ty.ptr_type(AddressSpace::default()),
-                        "dest",
-                    );
-
                     bin.emit_static_loop_with_int(
                         function,
                         bin.context.i64_type().const_zero(),
@@ -151,15 +138,21 @@ impl StorageSlot for SubstrateTarget {
                         slot,
                         |index: IntValue<'a>, slot: &mut IntValue<'a>| {
                             let elem = unsafe {
-                                bin.builder
-                                    .build_gep(dest, &[i32_zero!(), index], "index_access")
+                                bin.builder.build_gep(
+                                    llvm_ty,
+                                    new,
+                                    &[i32_zero!(), index],
+                                    "index_access",
+                                )
                             };
 
                             let val =
                                 self.storage_load_slot(bin, &ty, slot, slot_ptr, function, ns);
 
-                            let val = if ty.deref_memory().is_fixed_reference_type() {
-                                bin.builder.build_load(val.into_pointer_value(), "elem")
+                            let val = if ty.deref_memory().is_fixed_reference_type(ns) {
+                                let load_ty = bin.llvm_type(ty.deref_any(), ns);
+                                bin.builder
+                                    .build_load(load_ty, val.into_pointer_value(), "elem")
                             } else {
                                 val
                             };
@@ -168,7 +161,7 @@ impl StorageSlot for SubstrateTarget {
                         },
                     );
 
-                    dest.into()
+                    new.into()
                 } else {
                     // iterate over dynamic array
                     let slot_ty = Type::Uint(256);
@@ -213,7 +206,7 @@ impl StorageSlot for SubstrateTarget {
 
                     let mut elem_slot = bin
                         .builder
-                        .build_load(slot_ptr, "elem_slot")
+                        .build_load(slot.get_type(), slot_ptr, "elem_slot")
                         .into_int_value();
 
                     bin.emit_loop_cond_first_with_int(
@@ -227,8 +220,12 @@ impl StorageSlot for SubstrateTarget {
                             let entry =
                                 self.storage_load_slot(bin, elem_ty, slot, slot_ptr, function, ns);
 
-                            let entry = if elem_ty.deref_memory().is_fixed_reference_type() {
-                                bin.builder.build_load(entry.into_pointer_value(), "elem")
+                            let entry = if elem_ty.deref_memory().is_fixed_reference_type(ns) {
+                                bin.builder.build_load(
+                                    bin.llvm_type(elem_ty.deref_memory(), ns),
+                                    entry.into_pointer_value(),
+                                    "elem",
+                                )
                             } else {
                                 entry
                             };
@@ -255,26 +252,25 @@ impl StorageSlot for SubstrateTarget {
                     .unwrap()
                     .into_pointer_value();
 
-                let dest = bin.builder.build_pointer_cast(
-                    new,
-                    llvm_ty.ptr_type(AddressSpace::default()),
-                    "dest",
-                );
-
                 for (i, field) in str_ty.definition(ns).fields.iter().enumerate() {
                     let val = self.storage_load_slot(bin, &field.ty, slot, slot_ptr, function, ns);
 
                     let elem = unsafe {
                         bin.builder.build_gep(
-                            dest,
+                            llvm_ty,
+                            new,
                             &[i32_zero!(), i32_const!(i as u64)],
                             field.name_as_str(),
                         )
                     };
 
-                    let val = if field.ty.deref_memory().is_fixed_reference_type() {
-                        bin.builder
-                            .build_load(val.into_pointer_value(), field.name_as_str())
+                    let val = if field.ty.deref_memory().is_fixed_reference_type(ns) {
+                        let load_ty = bin.llvm_type(field.ty.deref_memory(), ns);
+                        bin.builder.build_load(
+                            load_ty,
+                            val.into_pointer_value(),
+                            field.name_as_str(),
+                        )
                     } else {
                         val
                     };
@@ -282,7 +278,7 @@ impl StorageSlot for SubstrateTarget {
                     bin.builder.build_store(elem, val);
                 }
 
-                dest.into()
+                new.into()
             }
             Type::String | Type::DynamicBytes => {
                 bin.builder.build_store(slot_ptr, *slot);
@@ -309,7 +305,8 @@ impl StorageSlot for SubstrateTarget {
                 bin.builder
                     .build_int_to_ptr(
                         ret,
-                        bin.llvm_type(ty.deref_any(), ns).into_pointer_type(),
+                        bin.llvm_type(ty.deref_any(), ns)
+                            .ptr_type(AddressSpace::default()),
                         "",
                     )
                     .into()
@@ -382,6 +379,7 @@ impl StorageSlot for SubstrateTarget {
                         |index: IntValue<'a>, slot: &mut IntValue<'a>| {
                             let mut elem = unsafe {
                                 bin.builder.build_gep(
+                                    bin.llvm_type(ty.deref_any(), ns),
                                     dest.into_pointer_value(),
                                     &[bin.context.i32_type().const_zero(), index],
                                     "index_access",
@@ -389,9 +387,14 @@ impl StorageSlot for SubstrateTarget {
                             };
 
                             if elem_ty.is_reference_type(ns)
-                                && !elem_ty.deref_memory().is_fixed_reference_type()
+                                && !elem_ty.deref_memory().is_fixed_reference_type(ns)
                             {
-                                elem = bin.builder.build_load(elem, "").into_pointer_value();
+                                let load_ty =
+                                    bin.llvm_type(elem_ty, ns).ptr_type(AddressSpace::default());
+                                elem = bin
+                                    .builder
+                                    .build_load(load_ty, elem, "")
+                                    .into_pointer_value();
                             }
 
                             self.storage_store_slot(
@@ -450,7 +453,7 @@ impl StorageSlot for SubstrateTarget {
                         ),
                     );
 
-                    self.set_storage(bin, slot_ptr, new_slot);
+                    self.set_storage(bin, slot_ptr, new_slot, bin.llvm_type(&slot_ty, ns));
 
                     self.keccak256_hash(
                         bin,
@@ -464,7 +467,11 @@ impl StorageSlot for SubstrateTarget {
 
                     let mut elem_slot = bin
                         .builder
-                        .build_load(new_slot, "elem_slot")
+                        .build_load(
+                            bin.llvm_type(&slot_ty, ns).into_int_type(),
+                            new_slot,
+                            "elem_slot",
+                        )
                         .into_int_value();
 
                     bin.emit_loop_cond_first_with_int(
@@ -475,8 +482,9 @@ impl StorageSlot for SubstrateTarget {
                         |elem_no: IntValue<'a>, slot: &mut IntValue<'a>| {
                             let index = bin.builder.build_int_mul(elem_no, elem_size, "");
 
-                            let data = unsafe {
+                            let mut elem = unsafe {
                                 bin.builder.build_gep(
+                                    bin.llvm_type(ty.deref_any(), ns),
                                     dest.into_pointer_value(),
                                     &[
                                         bin.context.i32_type().const_zero(),
@@ -487,16 +495,13 @@ impl StorageSlot for SubstrateTarget {
                                 )
                             };
 
-                            let mut elem = bin.builder.build_pointer_cast(
-                                data,
-                                llvm_elem_ty.ptr_type(AddressSpace::default()),
-                                "entry",
-                            );
-
                             if elem_ty.is_reference_type(ns)
-                                && !elem_ty.deref_memory().is_fixed_reference_type()
+                                && !elem_ty.deref_memory().is_fixed_reference_type(ns)
                             {
-                                elem = bin.builder.build_load(elem, "").into_pointer_value();
+                                elem = bin
+                                    .builder
+                                    .build_load(llvm_elem_ty, elem, "")
+                                    .into_pointer_value();
                             }
 
                             self.storage_store_slot(
@@ -544,6 +549,7 @@ impl StorageSlot for SubstrateTarget {
                 for (i, field) in str_ty.definition(ns).fields.iter().enumerate() {
                     let mut elem = unsafe {
                         bin.builder.build_gep(
+                            bin.llvm_type(ty.deref_any(), ns),
                             dest.into_pointer_value(),
                             &[
                                 bin.context.i32_type().const_zero(),
@@ -553,10 +559,13 @@ impl StorageSlot for SubstrateTarget {
                         )
                     };
 
-                    if field.ty.is_reference_type(ns) && !field.ty.is_fixed_reference_type() {
+                    if field.ty.is_reference_type(ns) && !field.ty.is_fixed_reference_type(ns) {
+                        let load_ty = bin
+                            .llvm_type(&field.ty, ns)
+                            .ptr_type(AddressSpace::default());
                         elem = bin
                             .builder
-                            .build_load(elem, field.name_as_str())
+                            .build_load(load_ty, elem, field.name_as_str())
                             .into_pointer_value();
                     }
 
@@ -589,7 +598,13 @@ impl StorageSlot for SubstrateTarget {
             Type::ExternalFunction { .. } => {
                 bin.builder.build_store(slot_ptr, *slot);
 
-                self.set_storage_extfunc(bin, function, slot_ptr, dest.into_pointer_value());
+                self.set_storage_extfunc(
+                    bin,
+                    function,
+                    slot_ptr,
+                    dest.into_pointer_value(),
+                    bin.llvm_type(ty, ns),
+                );
             }
             Type::InternalFunction { .. } => {
                 let ptr_ty = bin
@@ -609,13 +624,18 @@ impl StorageSlot for SubstrateTarget {
 
                 bin.builder.build_store(slot_ptr, *slot);
 
-                self.set_storage(bin, slot_ptr, m);
+                self.set_storage(bin, slot_ptr, m, ptr_ty.as_basic_type_enum());
             }
             Type::Address(_) | Type::Contract(_) => {
                 if dest.is_pointer_value() {
                     bin.builder.build_store(slot_ptr, *slot);
 
-                    self.set_storage(bin, slot_ptr, dest.into_pointer_value());
+                    self.set_storage(
+                        bin,
+                        slot_ptr,
+                        dest.into_pointer_value(),
+                        bin.llvm_type(ty, ns),
+                    );
                 } else {
                     let address = bin.builder.build_alloca(bin.address_type(ns), "address");
 
@@ -623,7 +643,12 @@ impl StorageSlot for SubstrateTarget {
 
                     bin.builder.build_store(slot_ptr, *slot);
 
-                    self.set_storage(bin, slot_ptr, address);
+                    self.set_storage(
+                        bin,
+                        slot_ptr,
+                        address,
+                        bin.address_type(ns).as_basic_type_enum(),
+                    );
                 }
             }
             _ => {
@@ -641,7 +666,7 @@ impl StorageSlot for SubstrateTarget {
                 // TODO ewasm allocates 32 bytes here, even though we have just
                 // allocated test. This can be folded into one allocation, if llvm
                 // does not already fold it into one.
-                self.set_storage(bin, slot_ptr, dest);
+                self.set_storage(bin, slot_ptr, dest, bin.llvm_type(ty.deref_any(), ns));
             }
         }
     }
@@ -700,7 +725,10 @@ impl StorageSlot for SubstrateTarget {
                         ns,
                     );
 
-                    let mut entry_slot = bin.builder.build_load(buf, "entry_slot").into_int_value();
+                    let mut entry_slot = bin
+                        .builder
+                        .build_load(slot.get_type(), buf, "entry_slot")
+                        .into_int_value();
 
                     // now loop from first slot to first slot + length
                     bin.emit_loop_cond_first_with_int(

+ 180 - 210
src/emit/substrate/target.rs

@@ -10,13 +10,12 @@ use crate::emit::{ContractArgs, TargetRuntime, Variable};
 use crate::sema::ast;
 use crate::sema::ast::{Function, Namespace, Type};
 use crate::{codegen, emit_context};
-use inkwell::types::{BasicType, IntType};
+use inkwell::types::{BasicType, BasicTypeEnum, IntType};
 use inkwell::values::{
-    ArrayValue, BasicMetadataValueEnum, BasicValueEnum, CallableValue, FunctionValue, IntValue,
-    PointerValue,
+    ArrayValue, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
 };
 use inkwell::{AddressSpace, IntPredicate};
-use solang_parser::pt::{self, Loc};
+use solang_parser::pt::Loc;
 use std::collections::HashMap;
 
 impl<'a> TargetRuntime<'a> for SubstrateTarget {
@@ -26,15 +25,15 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         _function: FunctionValue,
         slot: PointerValue,
         dest: PointerValue,
+        dest_ty: BasicTypeEnum,
     ) {
         emit_context!(binary);
 
         let ret = seal_set_storage!(
-            cast_byte_ptr!(slot).into(),
+            slot.into(),
             i32_const!(32).into(),
-            cast_byte_ptr!(dest).into(),
-            dest.get_type()
-                .get_element_type()
+            dest.into(),
+            dest_ty
                 .size_of()
                 .unwrap()
                 .const_cast(binary.context.i32_type(), false)
@@ -53,33 +52,32 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
     ) -> PointerValue<'a> {
         emit_context!(binary);
 
-        let ty = binary.llvm_type(
-            &ast::Type::ExternalFunction {
-                params: Vec::new(),
-                mutability: ast::Mutability::Nonpayable(pt::Loc::Codegen),
-                returns: Vec::new(),
-            },
-            ns,
-        );
+        // This is the size of the external function struct
+        let len = ns.address_length + 4;
 
-        let len = ty
-            .size_of()
-            .unwrap()
-            .const_cast(binary.context.i32_type(), false);
-
-        let ef = call!("__malloc", &[len.into()])
-            .try_as_basic_value()
-            .left()
-            .unwrap()
-            .into_pointer_value();
+        let ef = call!(
+            "__malloc",
+            &[binary
+                .context
+                .i32_type()
+                .const_int(len as u64, false)
+                .into()]
+        )
+        .try_as_basic_value()
+        .left()
+        .unwrap()
+        .into_pointer_value();
 
         let scratch_len = binary.scratch_len.unwrap().as_pointer_value();
-        binary.builder.build_store(scratch_len, len);
+        binary.builder.build_store(
+            scratch_len,
+            binary.context.i64_type().const_int(len as u64, false),
+        );
 
         let ret = call!(
             "seal_get_storage",
             &[
-                cast_byte_ptr!(slot).into(),
+                slot.into(),
                 i32_const!(32).into(),
                 ef.into(),
                 scratch_len.into()
@@ -94,9 +92,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         // TODO: decide behaviour if not exist
 
-        binary
-            .builder
-            .build_pointer_cast(ef, ty.ptr_type(AddressSpace::default()), "function_type")
+        ef
     }
 
     fn set_storage_string(
@@ -127,12 +123,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         binary.builder.position_at_end(set_block);
 
-        let ret = seal_set_storage!(
-            cast_byte_ptr!(slot).into(),
-            i32_const!(32).into(),
-            cast_byte_ptr!(data).into(),
-            len.into()
-        );
+        let ret = seal_set_storage!(slot.into(), i32_const!(32).into(), data.into(), len.into());
 
         log_return_code(binary, "seal_set_storage", ret);
 
@@ -140,14 +131,11 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         binary.builder.position_at_end(delete_block);
 
-        let ret = call!(
-            "seal_clear_storage",
-            &[cast_byte_ptr!(slot).into(), i32_const!(32).into()]
-        )
-        .try_as_basic_value()
-        .left()
-        .unwrap()
-        .into_int_value();
+        let ret = call!("seal_clear_storage", &[slot.into(), i32_const!(32).into()])
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_int_value();
 
         log_return_code(binary, "seal_clear_storage", ret);
 
@@ -171,7 +159,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         binary.builder.build_store(scratch_len, ty_len);
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot).into(),
+            slot.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -196,13 +184,10 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         binary.builder.position_at_end(retrieve_block);
 
-        let dest = binary.builder.build_pointer_cast(
-            binary.scratch.unwrap().as_pointer_value(),
-            ty.ptr_type(AddressSpace::default()),
-            "scratch_ty_buf",
-        );
-
-        let loaded_int = binary.builder.build_load(dest, "int");
+        let loaded_int =
+            binary
+                .builder
+                .build_load(ty, binary.scratch.unwrap().as_pointer_value(), "int");
 
         binary.builder.build_unconditional_branch(done_storage);
 
@@ -231,7 +216,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot).into(),
+            slot.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -266,7 +251,10 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         binary.builder.position_at_end(retrieve_block);
 
-        let length = binary.builder.build_load(scratch_len, "string_len");
+        let length =
+            binary
+                .builder
+                .build_load(binary.context.i32_type(), scratch_len, "string_len");
 
         let loaded_string = call!(
             "vector_new",
@@ -321,7 +309,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -340,7 +328,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .builder
             .build_select(
                 exists,
-                binary.builder.build_load(scratch_len, "string_len"),
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len"),
                 i32_zero!().into(),
                 "string_length",
             )
@@ -373,13 +363,17 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         let offset = unsafe {
             binary.builder.build_gep(
+                binary.context.i8_type().array_type(SCRATCH_SIZE),
                 binary.scratch.unwrap().as_pointer_value(),
                 &[i32_zero!(), index],
                 "data_offset",
             )
         };
 
-        binary.builder.build_load(offset, "value").into_int_value()
+        binary
+            .builder
+            .build_load(binary.context.i8_type(), offset, "value")
+            .into_int_value()
     }
 
     fn set_storage_bytes_subscript(
@@ -404,7 +398,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -423,7 +417,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .builder
             .build_select(
                 exists,
-                binary.builder.build_load(scratch_len, "string_len"),
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len"),
                 i32_zero!().into(),
                 "string_length",
             )
@@ -455,6 +451,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         let offset = unsafe {
             binary.builder.build_gep(
+                binary.context.i8_type().array_type(SCRATCH_SIZE),
                 binary.scratch.unwrap().as_pointer_value(),
                 &[i32_zero!(), index],
                 "data_offset",
@@ -465,7 +462,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         binary.builder.build_store(offset, val);
 
         let ret = seal_set_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             length.into()
@@ -500,7 +497,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64 - 1));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -519,7 +516,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .builder
             .build_select(
                 exists,
-                binary.builder.build_load(scratch_len, "string_len"),
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len"),
                 i32_zero!().into(),
                 "string_length",
             )
@@ -528,6 +527,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         // set the result
         let offset = unsafe {
             binary.builder.build_gep(
+                binary.context.i8_type().array_type(SCRATCH_SIZE),
                 binary.scratch.unwrap().as_pointer_value(),
                 &[i32_zero!(), length],
                 "data_offset",
@@ -542,7 +542,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_int_add(length, i32_const!(1), "new_length");
 
         let ret = seal_set_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             length.into()
@@ -558,7 +558,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         &self,
         binary: &Binary<'a>,
         function: FunctionValue<'a>,
-        _ty: &ast::Type,
+        ty: &ast::Type,
         slot: IntValue<'a>,
         load: bool,
         ns: &ast::Namespace,
@@ -576,7 +576,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -595,7 +595,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .builder
             .build_select(
                 exists,
-                binary.builder.build_load(scratch_len, "string_len"),
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len"),
                 i32_zero!().into(),
                 "string_length",
             )
@@ -635,19 +637,24 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         let val = if load {
             let offset = unsafe {
                 binary.builder.build_gep(
+                    binary.context.i8_type().array_type(SCRATCH_SIZE),
                     binary.scratch.unwrap().as_pointer_value(),
                     &[i32_zero!(), new_length],
                     "data_offset",
                 )
             };
 
-            Some(binary.builder.build_load(offset, "popped_value"))
+            Some(
+                binary
+                    .builder
+                    .build_load(binary.llvm_type(ty, ns), offset, "popped_value"),
+            )
         } else {
             None
         };
 
         let ret = seal_set_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             new_length.into()
@@ -679,7 +686,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
         let exists = seal_get_storage!(
-            cast_byte_ptr!(slot_ptr).into(),
+            slot_ptr.into(),
             i32_const!(32).into(),
             scratch_buf.into(),
             scratch_len.into()
@@ -698,7 +705,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .builder
             .build_select(
                 exists,
-                binary.builder.build_load(scratch_len, "string_len"),
+                binary
+                    .builder
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len"),
                 i32_zero!().into(),
                 "string_length",
             )
@@ -740,11 +749,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         call!(
             "seal_hash_keccak_256",
-            &[
-                cast_byte_ptr!(src).into(),
-                length.into(),
-                cast_byte_ptr!(dest).into()
-            ]
+            &[src.into(), length.into(), dest.into()]
         );
     }
 
@@ -792,9 +797,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             false,
         );
 
-        let callable = CallableValue::try_from(asm).unwrap();
-
-        binary.builder.build_call(callable, &[], "unreachable");
+        binary
+            .builder
+            .build_indirect_call(asm_fn, asm, &[], "unreachable");
 
         binary.builder.build_unreachable();
     }
@@ -804,24 +809,22 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         binary: &Binary<'b>,
         function: FunctionValue,
         args: &mut Vec<BasicValueEnum<'b>>,
-        data: PointerValue<'b>,
+        mut data: PointerValue<'b>,
         datalength: IntValue<'b>,
         spec: &[ast::Parameter],
         ns: &ast::Namespace,
     ) {
-        let mut argsdata = binary.builder.build_pointer_cast(
-            data,
-            binary.context.i8_type().ptr_type(AddressSpace::default()),
-            "",
-        );
-
-        let argsend = unsafe { binary.builder.build_gep(argsdata, &[datalength], "argsend") };
+        let argsend = unsafe {
+            binary
+                .builder
+                .build_gep(binary.context.i8_type(), data, &[datalength], "argsend")
+        };
 
         for param in spec {
-            args.push(self.decode_ty(binary, function, &param.ty, &mut argsdata, argsend, ns));
+            args.push(self.decode_ty(binary, function, &param.ty, &mut data, argsend, ns));
         }
 
-        self.check_overrun(binary, function, argsdata, argsend, true);
+        self.check_overrun(binary, function, data, argsend, true);
     }
 
     /// ABI encode into a vector for abi.encode* style builtin functions
@@ -882,43 +885,41 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             .unwrap()
             .into_pointer_value();
 
-        let v = binary.builder.build_pointer_cast(
-            p,
-            binary
-                .module
-                .get_struct_type("struct.vector")
-                .unwrap()
-                .ptr_type(AddressSpace::default()),
-            "string",
-        );
-
         // if it's packed, we have the correct length already
         if args.is_empty() {
             let data_len = unsafe {
-                binary
-                    .builder
-                    .build_gep(v, &[i32_zero!(), i32_zero!()], "data_len")
+                binary.builder.build_gep(
+                    binary.module.get_struct_type("struct.vector").unwrap(),
+                    p,
+                    &[i32_zero!(), i32_zero!()],
+                    "data_len",
+                )
             };
 
             binary.builder.build_store(data_len, length);
         }
 
         let data_size = unsafe {
-            binary
-                .builder
-                .build_gep(v, &[i32_zero!(), i32_const!(1)], "data_size")
+            binary.builder.build_gep(
+                binary.module.get_struct_type("struct.vector").unwrap(),
+                p,
+                &[i32_zero!(), i32_const!(1)],
+                "data_size",
+            )
         };
 
         binary.builder.build_store(data_size, length);
 
         let data = unsafe {
-            binary
-                .builder
-                .build_gep(v, &[i32_zero!(), i32_const!(2)], "data")
+            binary.builder.build_gep(
+                binary.module.get_struct_type("struct.vector").unwrap(),
+                p,
+                &[i32_zero!(), i32_const!(2)],
+                "data",
+            )
         };
 
         // now encode each of the arguments
-        let data = binary.builder.build_pointer_cast(data, byte_ptr!(), "");
 
         let mut argsdata = data;
 
@@ -948,15 +949,18 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             );
 
             let data_len = unsafe {
-                binary
-                    .builder
-                    .build_gep(v, &[i32_zero!(), i32_zero!()], "data_len")
+                binary.builder.build_gep(
+                    binary.module.get_struct_type("struct.vector").unwrap(),
+                    p,
+                    &[i32_zero!(), i32_zero!()],
+                    "data_len",
+                )
             };
 
             binary.builder.build_store(data_len, length);
         }
 
-        v
+        p
     }
 
     ///  ABI encode the return values for the function
@@ -1005,17 +1009,11 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         let mut argsdata = data;
 
         if let Some(selector) = selector {
-            binary.builder.build_store(
-                binary.builder.build_pointer_cast(
-                    data,
-                    selector.get_type().ptr_type(AddressSpace::default()),
-                    "",
-                ),
-                selector,
-            );
+            binary.builder.build_store(data, selector);
 
             argsdata = unsafe {
                 binary.builder.build_gep(
+                    binary.context.i8_type(),
                     data,
                     &[selector
                         .get_type()
@@ -1093,24 +1091,10 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         // salt
         let salt_buf =
             binary.build_alloca(function, binary.context.i8_type().array_type(36), "salt");
-        let salt_buf = binary
-            .builder
-            .build_pointer_cast(salt_buf, byte_ptr!(), "salt_buf");
         let salt_len = i32_const!(32);
 
         if let Some(salt) = contract_args.salt {
-            let salt_ty = ast::Type::Uint(256);
-
-            binary.builder.build_store(
-                binary.builder.build_pointer_cast(
-                    salt_buf,
-                    binary
-                        .llvm_type(&salt_ty, ns)
-                        .ptr_type(AddressSpace::default()),
-                    "salt",
-                ),
-                salt,
-            );
+            binary.builder.build_store(salt_buf, salt);
         } else {
             let (ptr, len) = self.contract_unique_salt(binary, contract_no, ns);
 
@@ -1141,7 +1125,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
             call!(
                 "seal_minimum_balance",
-                &[cast_byte_ptr!(value_ptr).into(), scratch_len.into()],
+                &[value_ptr.into(), scratch_len.into()],
                 "minimum_balance"
             );
         }
@@ -1170,7 +1154,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             &[
                 codehash.into(),
                 gas.into(),
-                cast_byte_ptr!(value_ptr, "value_transfer").into(),
+                value_ptr.into(),
                 encoded_args.into(),
                 encoded_args_len.into(),
                 address.into(),
@@ -1218,7 +1202,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                 scratch_buf,
                 binary
                     .builder
-                    .build_load(scratch_len, "string_len")
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len")
                     .into_int_value(),
             );
 
@@ -1264,7 +1248,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                 i32_zero!().into(), // TODO implement flags (mostly used for proxy calls)
                 address.unwrap().into(),
                 gas.into(),
-                cast_byte_ptr!(value_ptr, "value_transfer").into(),
+                value_ptr.into(),
                 payload.into(),
                 payload_len.into(),
                 scratch_buf.into(),
@@ -1303,7 +1287,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                 scratch_buf,
                 binary
                     .builder
-                    .build_load(scratch_len, "string_len")
+                    .build_load(binary.context.i32_type(), scratch_len, "string_len")
                     .into_int_value(),
             );
 
@@ -1336,7 +1320,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             &[
                 address.into(),
                 i32_const!(ns.address_length as u64).into(),
-                cast_byte_ptr!(value_ptr, "value_transfer").into(),
+                value_ptr.into(),
                 i32_const!(ns.value_length as u64).into()
             ]
         )
@@ -1378,7 +1362,10 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         let (scratch_buf, scratch_len) = scratch_buf!();
 
-        let length = binary.builder.build_load(scratch_len, "string_len");
+        let length =
+            binary
+                .builder
+                .build_load(binary.context.i32_type(), scratch_len, "string_len");
 
         call!(
             "vector_new",
@@ -1406,13 +1393,13 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         call!(
             "seal_value_transferred",
-            &[cast_byte_ptr!(value).into(), value_len.into()],
+            &[value.into(), value_len.into()],
             "value_transferred"
         );
 
         binary
             .builder
-            .build_load(value, "value_transferred")
+            .build_load(binary.value_type(ns), value, "value_transferred")
             .into_int_value()
     }
 
@@ -1426,11 +1413,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         binary.builder.build_store(address, addr);
 
-        call!(
-            "seal_terminate",
-            &[cast_byte_ptr!(address).into()],
-            "terminated"
-        );
+        call!("seal_terminate", &[address.into()], "terminated");
 
         binary.builder.build_unreachable();
     }
@@ -1471,14 +1454,17 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         call!(
             "__beNtoleN",
-            &[
-                res.into(),
-                cast_byte_ptr!(temp).into(),
-                i32_const!(hashlen).into()
-            ]
+            &[res.into(), temp.into(), i32_const!(hashlen).into()]
         );
 
-        binary.builder.build_load(temp, "hash").into_int_value()
+        binary
+            .builder
+            .build_load(
+                binary.llvm_type(&ast::Type::Bytes(hashlen as u8), ns),
+                temp,
+                "hash",
+            )
+            .into_int_value()
     }
 
     /// Emit event
@@ -1521,17 +1507,17 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
             );
 
             let mut dest = unsafe {
-                binary
-                    .builder
-                    .build_gep(topic_buf, &[i32_const!(1)], "dest")
+                binary.builder.build_gep(
+                    binary.context.i8_type(),
+                    topic_buf,
+                    &[i32_const!(1)],
+                    "dest",
+                )
             };
 
             call!(
                 "__bzero8",
-                &[
-                    cast_byte_ptr!(dest, "dest").into(),
-                    i32_const!(topic_count as u64 * 4).into()
-                ]
+                &[dest.into(), i32_const!(topic_count as u64 * 4).into()]
             );
 
             for topic in topics.iter() {
@@ -1544,7 +1530,14 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     ]
                 );
 
-                dest = unsafe { binary.builder.build_gep(dest, &[i32_const!(32)], "dest") };
+                dest = unsafe {
+                    binary.builder.build_gep(
+                        binary.context.i8_type(),
+                        dest,
+                        &[i32_const!(32)],
+                        "dest",
+                    )
+                };
             }
 
             topic_buf
@@ -1599,14 +1592,8 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                 call!($func, &[scratch_buf.into(), scratch_len.into()], $name);
 
                 binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        scratch_buf,
-                        binary
-                            .context
-                            .custom_width_int_type($width)
-                            .ptr_type(AddressSpace::default()),
-                        "",
-                    ),
+                    binary.context.custom_width_int_type($width),
+                    scratch_buf,
                     $name,
                 )
             }};
@@ -1620,7 +1607,11 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     &[
                         binary
                             .builder
-                            .build_load(binary.calldata_len.as_pointer_value(), "calldata_len")
+                            .build_load(
+                                binary.context.i32_type(),
+                                binary.calldata_len.as_pointer_value(),
+                                "calldata_len"
+                            )
                             .into(),
                         i32_const!(1).into(),
                         binary
@@ -1639,6 +1630,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
                 let data = unsafe {
                     binary.builder.build_gep(
+                        binary.context.get_struct_type("struct.vector").unwrap(),
                         v.into_pointer_value(),
                         &[i32_zero!(), i32_const!(2)],
                         "",
@@ -1653,11 +1645,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     .build_store(scratch_len, i32_const!(SCRATCH_SIZE as u64));
 
                 // retrieve the data
-                call!(
-                    "seal_input",
-                    &[cast_byte_ptr!(data).into(), scratch_len.into()],
-                    "data"
-                );
+                call!("seal_input", &[data.into(), scratch_len.into()], "data");
 
                 v
             }
@@ -1713,14 +1701,10 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                 );
 
                 binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        scratch_buf,
-                        binary
-                            .context
-                            .custom_width_int_type(ns.value_length as u32 * 8)
-                            .ptr_type(AddressSpace::default()),
-                        "",
-                    ),
+                    binary
+                        .context
+                        .custom_width_int_type(ns.value_length as u32 * 8),
+                    scratch_buf,
                     "price",
                 )
             }
@@ -1737,14 +1721,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     "caller"
                 );
 
-                binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        scratch_buf,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    "caller",
-                )
+                binary
+                    .builder
+                    .build_load(binary.address_type(ns), scratch_buf, "caller")
             }
             codegen::Expression::Builtin(_, _, codegen::Builtin::Value, _) => {
                 self.value_transferred(binary, ns).into()
@@ -1769,14 +1748,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     "address"
                 );
 
-                binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        scratch_buf,
-                        binary.address_type(ns).ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    "self_address",
-                )
+                binary
+                    .builder
+                    .build_load(binary.address_type(ns), scratch_buf, "self_address")
             }
             codegen::Expression::Builtin(_, _, codegen::Builtin::Balance, _) => {
                 let (scratch_buf, scratch_len) = scratch_buf!();
@@ -1791,14 +1765,9 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
                     "balance"
                 );
 
-                binary.builder.build_load(
-                    binary.builder.build_pointer_cast(
-                        scratch_buf,
-                        binary.value_type(ns).ptr_type(AddressSpace::default()),
-                        "",
-                    ),
-                    "balance",
-                )
+                binary
+                    .builder
+                    .build_load(binary.value_type(ns), scratch_buf, "balance")
             }
             _ => unreachable!("{:?}", expr),
         }
@@ -1853,6 +1822,7 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
         _function: FunctionValue<'a>,
         _builtin_func: &Function,
         _args: &[BasicMetadataValueEnum<'a>],
+        _first_arg_type: BasicTypeEnum,
         _ns: &Namespace,
     ) -> BasicValueEnum<'a> {
         unimplemented!()

+ 1 - 1
src/sema/expression/mod.rs

@@ -110,7 +110,7 @@ impl Expression {
 
         // First of all, if we have a ref then derefence it
         if let Type::Ref(r) = &from {
-            return if r.is_fixed_reference_type() {
+            return if r.is_fixed_reference_type(ns) {
                 // A struct/fixed array *value* is simply the type, e.g. Type::Struct(_)
                 // An assignable struct value, e.g. member of another struct, is Type::Ref(Type:Struct(_)).
                 // However, the underlying types are identical: simply a pointer.

+ 1 - 1
src/sema/expression/subscript.rs

@@ -105,7 +105,7 @@ pub(super) fn array_subscript(
 
                 array = array.cast(
                     &array.loc(),
-                    if array_ty.deref_memory().is_fixed_reference_type() {
+                    if array_ty.deref_memory().is_fixed_reference_type(ns) {
                         &array_ty
                     } else {
                         array_ty.deref_any()

+ 8 - 4
src/sema/types.rs

@@ -1025,7 +1025,7 @@ impl Type {
         }
     }
 
-    /// Give the type of an memory array after dereference
+    /// Give the type of a memory array after dereference
     #[must_use]
     pub fn array_deref(&self) -> Self {
         match self {
@@ -1050,7 +1050,7 @@ impl Type {
     }
 
     /// Is this a reference type of fixed size
-    pub fn is_fixed_reference_type(&self) -> bool {
+    pub fn is_fixed_reference_type(&self, ns: &Namespace) -> bool {
         match self {
             Type::Bool => false,
             Type::Address(_) => false,
@@ -1068,7 +1068,9 @@ impl Type {
             Type::Ref(_) => false,
             Type::StorageRef(..) => false,
             Type::InternalFunction { .. } => false,
-            Type::ExternalFunction { .. } => false,
+            // On EVM, an external function is saved on an 256-bit register, so it is not
+            // a reference type.
+            Type::ExternalFunction { .. } => ns.target != Target::EVM,
             Type::Slice(_) => false,
             Type::Unresolved => false,
             Type::FunctionSelector => false,
@@ -1490,7 +1492,9 @@ impl Type {
             Type::Ref(r) => r.is_reference_type(ns),
             Type::StorageRef(_, r) => r.is_reference_type(ns),
             Type::InternalFunction { .. } => false,
-            Type::ExternalFunction { .. } => false,
+            // On EVM, an external function is saved on an 256-bit register, so it is not
+            // a reference type.
+            Type::ExternalFunction { .. } => ns.target != Target::EVM,
             Type::UserType(no) => ns.user_types[*no].ty.is_reference_type(ns),
             _ => false,
         }

+ 6 - 2
stdlib/Makefile

@@ -1,5 +1,6 @@
 CC=clang
-CFLAGS=$(TARGET_FLAGS) -emit-llvm -O3 -ffreestanding -fno-builtin -Wall -Wno-unused-function
+BIT_INT_FLAGS=-Xclang -fexperimental-max-bitint-width=512
+CFLAGS=$(TARGET_FLAGS) -emit-llvm -O3 -ffreestanding -fno-builtin -Wall -Wno-unused-function $(BIT_INT_FLAGS)
 
 bpf/%.bc wasm/%.bc: %.c
 	$(CC) -c $(CFLAGS) $< -o $@
@@ -9,7 +10,10 @@ WASM=$(addprefix wasm/,ripemd160.bc stdlib.bc substrate.bc bigint.bc format.bc h
 
 all: $(SOLANA) $(WASM)
 
-$(SOLANA): TARGET_FLAGS=--target=bpfel -march=bpfel+solana
+$(SOLANA): TARGET_FLAGS=--target=sbf -march=bpfel+solana
 $(WASM): TARGET_FLAGS=--target=wasm32
 
 bpf/solana.bc: solana.c solana_sdk.h
+
+clean:
+	rm -r bpf/* wasm/*

+ 2 - 2
stdlib/bigint.c

@@ -430,7 +430,7 @@ int sdivmod128(__uint128_t *pdividend, __uint128_t *pdivisor, __uint128_t *remai
     return 0;
 }
 
-typedef unsigned _ExtInt(256) uint256_t;
+typedef unsigned _BitInt(256) uint256_t;
 uint256_t const uint256_0 = (uint256_t)0;
 uint256_t const uint256_1 = (uint256_t)1;
 
@@ -544,7 +544,7 @@ int sdivmod256(uint256_t *pdividend, uint256_t *pdivisor, uint256_t *remainder,
     return 0;
 }
 
-typedef unsigned _ExtInt(512) uint512_t;
+typedef unsigned _BitInt(512) uint512_t;
 uint512_t const uint512_0 = (uint512_t)0;
 uint512_t const uint512_1 = (uint512_t)1;
 

BIN
stdlib/bpf/bigint.bc


BIN
stdlib/bpf/format.bc


BIN
stdlib/bpf/heap.bc


BIN
stdlib/bpf/ripemd160.bc


BIN
stdlib/bpf/solana.bc


BIN
stdlib/bpf/stdlib.bc


+ 1 - 1
stdlib/format.c

@@ -179,7 +179,7 @@ char *uint128dec(char *output, __uint128_t val128)
     return output;
 }
 
-typedef unsigned _ExtInt(256) uint256_t;
+typedef unsigned _BitInt(256) uint256_t;
 
 extern int udivmod256(const uint256_t *dividend, const uint256_t *divisor, uint256_t *remainder, uint256_t *quotient);
 

BIN
stdlib/wasm/bigint.bc


BIN
stdlib/wasm/format.bc


BIN
stdlib/wasm/heap.bc


BIN
stdlib/wasm/ripemd160.bc


BIN
stdlib/wasm/stdlib.bc


BIN
stdlib/wasm/substrate.bc


+ 1 - 1
tests/codegen_testcases/solidity/array_of_struct.sol

@@ -12,7 +12,7 @@ contract c {
         uint64[4] f2;
     }
 
-// BEGIN-CHECK: @"c::c::function::foo__c.S"({ [2 x i8], i1, [3 x { [2 x i1], [4 x i64] }] }* %0
+// BEGIN-CHECK: @"c::c::function::foo__c.S"(ptr %17, ptr %0)
     function foo(S s) public pure {
     }
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels