Compare commits

..

3 Commits

Author SHA1 Message Date
Cyrill Leutwiler b19981a513 division functions
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-07-04 16:18:30 +02:00
Cyrill Leutwiler 10e50e446b restore
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-07-04 15:51:00 +02:00
Cyrill Leutwiler 939a8f2f78 add simulated evm math opcode syscalls
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-07-04 15:45:59 +02:00
37 changed files with 297 additions and 898 deletions
-10
View File
@@ -1,13 +1,3 @@
#!/usr/bin/env python3
"""
This script generates JSON files for different platforms based on GitHub release data.
It fetches release information from a specified GitHub repository and tag,
parses the release assets, and generates JSON files for each platform with relevant metadata.
It also handles checksum files and updates a list.json file for each platform.
It requires the GITHUB_TOKEN environment variable to be set for authentication.
Usage:
python json_generator.py <repo> <tag>
"""
import os
import sys
import json
-155
View File
@@ -1,155 +0,0 @@
#!/usr/bin/env python3
"""
This script generates JSON files for different platforms based on GitHub data.
Requires the GITHUB_SHA, FIRST_SOLC_VERSION, LAST_SOLC_VERSION, TAG and FILEPATH environment variables to be set.
Usage:
python json_generator_nightly.py
"""
import os
import sys
import json
from datetime import datetime
def validate_env_variables():
"""Validate that environment variables are set."""
if "GITHUB_SHA" not in os.environ:
print("Error: GITHUB_SHA environment variable is not set.")
sys.exit(1)
if "FIRST_SOLC_VERSION" not in os.environ:
print("Error: FIRST_SOLC_VERSION environment variable is not set.")
sys.exit(1)
if "LAST_SOLC_VERSION" not in os.environ:
print("Error: LAST_SOLC_VERSION environment variable is not set.")
sys.exit(1)
if "TAG" not in os.environ:
print("Error: TAG environment variable is not set.")
sys.exit(1)
if "FILEPATH" not in os.environ:
print("Error: FILEPATH environment variable is not set.")
sys.exit(1)
def fetch_data_file():
"""
Fetch the data.json file with artifacts urls and sha256 checksums
and parse it into a single dictionary mapping artifact names to their URLs and SHAs.
"""
# read data.json file
artifacts_data = {}
data_file_path = os.environ["FILEPATH"]
if not os.path.exists(data_file_path):
print("Error: data.json file not found.")
sys.exit(1)
with open(data_file_path, 'r') as f:
try:
artifacts_data = json.load(f)
except json.JSONDecodeError:
print("Error: data.json file is not a valid JSON.")
sys.exit(1)
result = {}
for item in artifacts_data:
for key, value in item.items():
if key.endswith('_url'):
base_key = key.rsplit('_url', 1)[0]
if base_key not in result:
result[base_key] = {}
result[base_key]['url'] = value
elif key.endswith('_sha'):
base_key = key.rsplit('_sha', 1)[0]
if base_key not in result:
result[base_key] = {}
result[base_key]['sha'] = value
return result
def extract_build_hash():
"""Extract the first 8 characters of the commit hash."""
sha = os.environ.get("GITHUB_SHA")
return f"commit.{sha[:8]}"
def generate_asset_json_nightly(name, url, checksum):
"""Generate JSON for a specific asset."""
# Date in format YYYY-MM-DD
date = datetime.now().strftime("%Y.%-m.%-d")
last_version = os.environ.get("TAG").replace('v','')
version = f"{last_version}-nightly.{date}"
SHA = os.environ.get("GITHUB_SHA", "")[:8]
build = f"commit.{SHA}"
long_version = f"{version}+{build}"
return {
"name": name,
"version": version,
"build": build,
"longVersion": long_version,
"url": url,
"sha256": checksum,
"firstSolcVersion": os.environ.get("FIRST_SOLC_VERSION"),
"lastSolcVersion": os.environ.get("LAST_SOLC_VERSION")
}
def save_platform_json(platform_folder, asset_json):
"""Save asset JSON and update list.json for a specific platform."""
# Create platform folder if it doesn't exist
os.makedirs(platform_folder, exist_ok=True)
# Update or create list.json
list_file_path = os.path.join(platform_folder, "list.json")
if os.path.exists(list_file_path):
with open(list_file_path, 'r') as f:
try:
list_data = json.load(f)
except json.JSONDecodeError:
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
else:
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
# Remove any existing entry with the same path
list_data['builds'] = [
build for build in list_data['builds']
if build['version'] != asset_json['version']
]
# Add the new build
list_data['builds'].append(asset_json)
# Update releases
version = asset_json['version']
list_data['releases'][version] = f"{asset_json['name']}+{asset_json['longVersion']}"
# Update latest release
list_data['latestRelease'] = version
with open(list_file_path, 'w') as f:
json.dump(list_data, f, indent=4)
def main():
validate_env_variables()
data = fetch_data_file()
# Mapping of asset names to platform folders
platform_mapping = {
'resolc-x86_64-unknown-linux-musl': 'linux',
'resolc-universal-apple-darwin': 'macos',
'resolc-x86_64-pc-windows-msvc': 'windows',
'resolc-web.js': 'wasm'
}
# Process each asset
for asset in data.keys():
platform_name = platform_mapping.get(asset)
if platform_name:
platform_folder = os.path.join(platform_name)
asset_json = generate_asset_json_nightly(asset, data[asset]['url'], data[asset]['sha'])
save_platform_json(platform_folder, asset_json)
print(f"Processed {asset} for {platform_name}")
if __name__ == "__main__":
main()
-385
View File
@@ -1,385 +0,0 @@
name: Nightly Release
on:
schedule:
# Run every day at 01:00 UTC
- cron: "0 1 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_MUSL_CROSS_IMAGE: messense/rust-musl-cross@sha256:c0154e992adb791c3b848dd008939d19862549204f8cb26f5ca7a00f629e6067
jobs:
# check if there were commits yesterday
check_commits:
runs-on: ubuntu-latest
outputs:
has_commits: ${{ steps.check_commits.outputs.has_commits }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch full history to check previous commits
ref: "main"
- name: Check for commits from yesterday
id: check_commits
run: |
# Get yesterday's date in YYYY-MM-DD format
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
echo "Checking for commits from: $YESTERDAY"
# Check if there were any commits yesterday
COMMIT_COUNT=$(git log --oneline --since="$YESTERDAY 00:00:00" --until="$YESTERDAY 23:59:59" | wc -l)
echo "Found $COMMIT_COUNT commits from yesterday"
if [ $COMMIT_COUNT -gt 0 ]; then
echo "has_commits=true" >> $GITHUB_OUTPUT
echo "✅ Found $COMMIT_COUNT commits from yesterday - continuing workflow"
else
echo "has_commits=false" >> $GITHUB_OUTPUT
echo "❌ No commits found from yesterday - skipping remaining steps"
echo "::notice::❌ No commits found from yesterday - skipping remaining steps"
fi
build:
# github actions matrix jobs don't support multiple outputs
# ugly workaround from https://github.com/orgs/community/discussions/17245#discussioncomment-11222880
if: ${{ needs.check_commits.outputs.has_commits == 'true' }}
outputs:
resolc-x86_64-unknown-linux-musl_url: ${{ steps.set-output.outputs.resolc-x86_64-unknown-linux-musl_url }}
resolc-x86_64-unknown-linux-musl_sha: ${{ steps.set-output.outputs.resolc-x86_64-unknown-linux-musl_sha }}
resolc-aarch64-apple-darwin_url: ${{ steps.set-output.outputs.resolc-aarch64-apple-darwin_url }}
resolc-aarch64-apple-darwin_sha: ${{ steps.set-output.outputs.resolc-aarch64-apple-darwin_sha }}
resolc-x86_64-apple-darwin_url: ${{ steps.set-output.outputs.resolc-x86_64-apple-darwin_url }}
resolc-x86_64-apple-darwin_sha: ${{ steps.set-output.outputs.resolc-x86_64-apple-darwin_sha }}
resolc-x86_64-pc-windows-msvc_url: ${{ steps.set-output.outputs.resolc-x86_64-pc-windows-msvc_url }}
resolc-x86_64-pc-windows-msvc_sha: ${{ steps.set-output.outputs.resolc-x86_64-pc-windows-msvc_sha }}
strategy:
matrix:
target:
[
x86_64-unknown-linux-musl,
aarch64-apple-darwin,
x86_64-apple-darwin,
x86_64-pc-windows-msvc,
]
include:
- target: x86_64-unknown-linux-musl
type: musl
runner: ubuntu-24.04
- target: aarch64-apple-darwin
type: native
runner: macos-14
- target: x86_64-apple-darwin
type: native
runner: macos-13
- target: x86_64-pc-windows-msvc
type: native
runner: windows-2022
runs-on: ${{ matrix.runner }}
needs: [check_commits]
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
# without this it will override our rust flags
rustflags: ""
cache-key: ${{ matrix.target }}
- name: Download LLVM
uses: ./.github/actions/get-llvm
with:
target: ${{ matrix.target }}
- name: Build
if: ${{ matrix.type == 'native' }}
shell: bash
run: |
export LLVM_SYS_181_PREFIX=$PWD/llvm-${{ matrix.target }}
make install-bin
mv target/release/resolc resolc-${{ matrix.target }} || mv target/release/resolc.exe resolc-${{ matrix.target }}.exe
- name: Build
if: ${{ matrix.type == 'musl' }}
run: |
docker run -v $PWD:/opt/revive $RUST_MUSL_CROSS_IMAGE /bin/bash -c "
cd /opt/revive
chown -R root:root .
apt update && apt upgrade -y && apt install -y pkg-config
export LLVM_SYS_181_PREFIX=/opt/revive/llvm-${{ matrix.target }}
make install-bin
mv target/${{ matrix.target }}/release/resolc resolc-${{ matrix.target }}
"
sudo chown -R $(id -u):$(id -g) .
- name: Install Solc
uses: ./.github/actions/get-solc
- name: Basic Sanity Check
shell: bash
run: |
result=$(./resolc-${{ matrix.target }} --bin crates/integration/contracts/flipper.sol)
echo $result
if [[ $result == *'0x50564d'* ]]; then exit 0; else exit 1; fi
- name: Upload artifacts (nightly)
uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: resolc-${{ matrix.target }}
path: resolc-${{ matrix.target }}*
retention-days: 40
- name: Set output variables (nightly)
id: set-output
shell: bash
run: |
echo "Artifact URL is ${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "Artifact SHA is ${{ steps.artifact-upload-step.outputs.artifact-digest }}"
echo "resolc-${{ matrix.target }}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "resolc-${{ matrix.target }}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}" >> "$GITHUB_OUTPUT"
echo "resolc-${{ matrix.target }}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}"
echo "resolc-${{ matrix.target }}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}" >> "$GITHUB_OUTPUT"
build-wasm:
runs-on: ubuntu-24.04
needs: [check_commits]
if: ${{ needs.check_commits.outputs.has_commits == 'true' }}
outputs:
resolc-web.js_url: ${{ steps.set-output.outputs.resolc_web_js_url }}
resolc-web.js_sha: ${{ steps.set-output.outputs.resolc_web_js_sha }}
env:
RELEASE_RESOLC_WASM_URI: https://github.com/paritytech/revive/releases/download/${{ github.ref_name }}/resolc.wasm
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
target: wasm32-unknown-emscripten
# without this it will override our rust flags
rustflags: ""
- name: Download Host LLVM
uses: ./.github/actions/get-llvm
with:
target: x86_64-unknown-linux-gnu
- name: Download Wasm LLVM
uses: ./.github/actions/get-llvm
with:
target: wasm32-unknown-emscripten
- name: Download EMSDK
uses: ./.github/actions/get-emsdk
- name: Build
run: |
export LLVM_SYS_181_PREFIX=$PWD/llvm-x86_64-unknown-linux-gnu
export REVIVE_LLVM_TARGET_PREFIX=$PWD/llvm-wasm32-unknown-emscripten
source emsdk/emsdk_env.sh
make install-wasm
chmod -x ./target/wasm32-unknown-emscripten/release/resolc.wasm
- name: Set Up Node.js
uses: actions/setup-node@v3
with:
node-version: "20"
- name: Basic Sanity Check
run: |
mkdir -p solc
curl -sSLo solc/soljson.js https://github.com/ethereum/solidity/releases/download/v0.8.30/soljson.js
node -e "
const soljson = require('solc/soljson');
const createRevive = require('./target/wasm32-unknown-emscripten/release/resolc.js');
const compiler = createRevive();
compiler.soljson = soljson;
const standardJsonInput =
{
language: 'Solidity',
sources: {
'MyContract.sol': {
content: 'pragma solidity ^0.8.0; contract MyContract { function greet() public pure returns (string memory) { return \'Hello\'; } }',
},
},
settings: { optimizer: { enabled: false } }
};
compiler.writeToStdin(JSON.stringify(standardJsonInput));
compiler.callMain(['--standard-json']);
// Collect output
const stdout = compiler.readFromStdout();
const stderr = compiler.readFromStderr();
if (stderr) { console.error(stderr); process.exit(1); }
let out = JSON.parse(stdout);
let bytecode = out.contracts['MyContract.sol']['MyContract'].evm.bytecode.object
console.log(bytecode);
if(!bytecode.startsWith('50564d')) { process.exit(1); }
"
- name: Compress Artifact
run: |
mkdir -p resolc-wasm32-unknown-emscripten
mv ./target/wasm32-unknown-emscripten/release/resolc.js ./resolc-wasm32-unknown-emscripten/
mv ./target/wasm32-unknown-emscripten/release/resolc.wasm ./resolc-wasm32-unknown-emscripten/
mv ./target/wasm32-unknown-emscripten/release/resolc_web.js ./resolc-wasm32-unknown-emscripten/
# There is no way to upload several files as several artifacts with a single upload-artifact step
# It's needed to have resolc_web.js separately for night builds for resolc-bin repo
# https://github.com/actions/upload-artifact/issues/331
- name: Upload artifact resolc.js (nightly)
uses: actions/upload-artifact@v4
with:
name: resolc.js
path: resolc-wasm32-unknown-emscripten/resolc.js
retention-days: 40
- name: Upload artifacts resolc.wasm (nightly)
uses: actions/upload-artifact@v4
with:
name: resolc.wasm
path: resolc-wasm32-unknown-emscripten/resolc.wasm
retention-days: 40
- name: Upload artifacts resolc_web.js (nightly)
uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: resolc_web.js
path: resolc-wasm32-unknown-emscripten/resolc_web.js
retention-days: 40
- name: Set output variables
id: set-output
env:
TARGET: resolc_web_js
run: |
echo "Artifact URL is ${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "Artifact SHA is ${{ steps.artifact-upload-step.outputs.artifact-digest }}"
echo "${TARGET}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "${TARGET}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}" >> "$GITHUB_OUTPUT"
echo "${TARGET}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}""
echo "${TARGET}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}"" >> "$GITHUB_OUTPUT"
create-macos-fat-binary:
if: ${{ needs.check_commits.outputs.has_commits == 'true' }}
needs: [build]
outputs:
resolc-universal-apple-darwin_url: ${{ steps.set-output.outputs.resolc-universal-apple-darwin_url }}
resolc-universal-apple-darwin_sha: ${{ steps.set-output.outputs.resolc-universal-apple-darwin_sha }}
runs-on: macos-14
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Create macOS Fat Binary
run: |
lipo resolc-aarch64-apple-darwin resolc-x86_64-apple-darwin -create -output resolc-universal-apple-darwin
- name: Make Executable
run: |
chmod +x resolc-universal-apple-darwin
- uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: resolc-universal-apple-darwin
path: resolc-universal-apple-darwin
retention-days: 40
- name: Set output variables
id: set-output
env:
TARGET: resolc-universal-apple-darwin
run: |
echo "Artifact URL is ${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "Artifact SHA is ${{ steps.artifact-upload-step.outputs.artifact-digest }}"
echo "${TARGET}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}"
echo "${TARGET}_url=${{ steps.artifact-upload-step.outputs.artifact-url }}" >> "$GITHUB_OUTPUT"
echo "${TARGET}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}""
echo "${TARGET}_sha=${{ steps.artifact-upload-step.outputs.artifact-digest }}"" >> "$GITHUB_OUTPUT"
generate-nightly-json:
runs-on: ubuntu-24.04
if: ${{ needs.check_commits.outputs.has_commits == 'true' }}
environment: tags
needs: [build-wasm, build, create-macos-fat-binary, check_commits]
steps:
- name: Checkout revive
uses: actions/checkout@v4
with:
path: revive
- name: Checkout resolc-bin
uses: actions/checkout@v4
with:
repository: paritytech/resolc-bin
path: resolc-bin
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
merge-multiple: true
path: bins
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.REVIVE_JSON_APP_ID }}
private-key: ${{ secrets.REVIVE_JSON_APP_KEY }}
owner: paritytech
repositories: resolc-bin
- name: Generate JSON
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TOKEN: ${{ steps.app-token.outputs.token }}
APP_NAME: "paritytech-revive-json"
Green: "\e[32m"
NC: "\e[0m"
run: |
echo '[' > data.json
echo '${{ toJSON(needs.build.outputs) }}' >> data.json
echo ',' >> data.json
echo '${{ toJSON(needs.build-wasm.outputs) }}' >> data.json
echo ',' >> data.json
echo '${{ toJSON(needs.create-macos-fat-binary.outputs) }}' >> data.json
echo ']' >> data.json
chmod +x bins/resolc-x86_64-unknown-linux-musl
export FIRST_SOLC_VERSION=$(./bins/resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 1 -d "," | tr -d ">=")
export LAST_SOLC_VERSION=$(./bins/resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 2 -d "," | tr -d "<=")
export FILEPATH=$(readlink -f data.json)
export TAG=$(cd revive;gh release list --json name,isLatest --jq '.[] | select(.isLatest)|.name')
cd resolc-bin
mkdir -p nightly
cd nightly
python3 ../../revive/.github/scripts/json_generator_nightly.py
cd ..
git status
echo "${Green}Add new remote with gh app token${NC}"
git remote set-url origin $(git config remote.origin.url | sed "s/github.com/${APP_NAME}:${TOKEN}@github.com/g")
echo "${Green}Remove http section that causes issues with gh app auth token${NC}"
sed -i.bak '/\[http/d' ./.git/config
sed -i.bak '/extraheader/d' ./.git/config
git config user.email "ci@parity.io"
git config user.name "${APP_NAME}"
git add nightly/
git commit -m "Update nightly json"
git push origin main
echo "::notice::nightly info.list files were successfully published to https://github.com/paritytech/resolc-bin"
-1
View File
@@ -14,7 +14,6 @@ concurrency:
env:
CARGO_TERM_COLOR: always
# if changed, dont forget to update the env var in release-nightly.yml
RUST_MUSL_CROSS_IMAGE: messense/rust-musl-cross@sha256:c0154e992adb791c3b848dd008939d19862549204f8cb26f5ca7a00f629e6067
jobs:
-13
View File
@@ -6,19 +6,6 @@ This is a development pre-release.
Supported `polkadot-sdk` rev: `2503.0.1`
## v0.4.0
This is a development pre-release.
Supported `polkadot-sdk` rev: `2503.0.1`
### Added
- Line debug information per YUL builtin and for `if` statements.
- Support for the YUL optimizer details in the standard json input definition.
### Fixed
- The debug info source file matches the YUL path in `--debug-output-dir`, allowing tools to display the source line.
## v0.3.0
This is a development pre-release.
+7 -7
View File
@@ -1,10 +1,10 @@
{
"Baseline": 945,
"Computation": 2308,
"DivisionArithmetics": 2334,
"ERC20": 21363,
"Events": 1677,
"FibonacciIterative": 1516,
"Baseline": 939,
"Computation": 2282,
"DivisionArithmetics": 8849,
"ERC20": 18308,
"Events": 1640,
"FibonacciIterative": 1497,
"Flipper": 2099,
"SHA1": 8268
"SHA1": 8243
}
+4 -39
View File
@@ -2,7 +2,6 @@
pub mod ir_type;
use std::path::Path;
use std::path::PathBuf;
use serde::Deserialize;
@@ -17,14 +16,6 @@ pub struct DebugConfig {
pub output_directory: Option<PathBuf>,
/// Whether debug info should be emitted.
pub emit_debug_info: bool,
/// The YUL debug output file path.
///
/// Is expected to be configured when running in YUL mode.
pub contract_path: Option<PathBuf>,
/// The YUL input file path.
///
/// Is expected to be configured when not running in YUL mode.
pub yul_path: Option<PathBuf>,
}
impl DebugConfig {
@@ -33,41 +24,15 @@ impl DebugConfig {
Self {
output_directory,
emit_debug_info,
contract_path: None,
yul_path: None,
}
}
/// Set the current YUL path.
pub fn set_yul_path(&mut self, yul_path: &Path) {
self.yul_path = yul_path.to_path_buf().into();
}
/// Set the current contract path.
pub fn set_contract_path(&mut self, contract_path: &str) {
self.contract_path = self.yul_source_path(contract_path);
}
/// Returns with the following precedence:
/// 1. The YUL source path if it was configured.
/// 2. The source YUL path from the debug output dir if it was configured.
/// 3. `None` if there is no debug output directory.
pub fn yul_source_path(&self, contract_path: &str) -> Option<PathBuf> {
if let Some(path) = self.yul_path.as_ref() {
return Some(path.clone());
}
self.output_directory.as_ref().map(|output_directory| {
let mut file_path = output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul);
file_path.push(full_file_name);
file_path
})
}
/// Dumps the Yul IR.
pub fn dump_yul(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
if let Some(file_path) = self.yul_source_path(contract_path) {
if let Some(output_directory) = self.output_directory.as_ref() {
let mut file_path = output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul);
file_path.push(full_file_name);
std::fs::write(file_path, code)?;
}
@@ -51,20 +51,11 @@ pub struct DebugInfo<'ctx> {
impl<'ctx> DebugInfo<'ctx> {
/// A shortcut constructor.
pub fn new(
module: &inkwell::module::Module<'ctx>,
debug_config: &crate::debug_config::DebugConfig,
) -> Self {
let module_name = module.get_name().to_string_lossy();
let yul_name = debug_config
.contract_path
.as_ref()
.map(|path| path.display().to_string());
pub fn new(module: &inkwell::module::Module<'ctx>) -> Self {
let (builder, compile_unit) = module.create_debug_info_builder(
true,
inkwell::debug_info::DWARFSourceLanguage::C,
yul_name.as_deref().unwrap_or_else(|| module_name.as_ref()),
module.get_name().to_string_lossy().as_ref(),
"",
"",
false,
@@ -15,8 +15,6 @@ use crate::optimizer::settings::size_level::SizeLevel;
use crate::optimizer::Optimizer;
use crate::polkavm::context::attribute::Attribute;
use crate::polkavm::context::pointer::Pointer;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
use self::declaration::Declaration;
use self::r#return::Return;
@@ -30,9 +28,7 @@ pub struct Function<'ctx> {
/// The LLVM function declaration.
declaration: Declaration<'ctx>,
/// The stack representation.
stack: HashMap<String, u64>,
/// The stack variables pointer.
stack_variables: Pointer<'ctx>,
stack: HashMap<String, Pointer<'ctx>>,
/// The return value entity.
r#return: Return<'ctx>,
@@ -60,14 +56,11 @@ impl<'ctx> Function<'ctx> {
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
return_block: inkwell::basic_block::BasicBlock<'ctx>,
stack_variables: Pointer<'ctx>,
) -> Self {
Self {
name,
declaration,
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
stack_variables,
r#return,
entry_block,
@@ -217,49 +210,22 @@ impl<'ctx> Function<'ctx> {
/// Saves the pointer to a stack variable, returning the pointer to the shadowed variable,
/// if it exists.
pub fn insert_stack_pointer<D: Dependency + Clone>(
pub fn insert_stack_pointer(
&mut self,
context: &mut Context<'ctx, D>,
name: String,
) -> Pointer<'ctx> {
let pointer_name = format!("{}_stack_pointer", &name);
let len = self.stack.len();
let index = *self.stack.entry(name).or_insert_with(|| len as u64);
let indices = &[
context.xlen_type().const_zero(),
context.xlen_type().const_int(index, false),
];
context.build_gep(
self.stack_variables,
indices,
context.word_type(),
&pointer_name,
)
pointer: Pointer<'ctx>,
) -> Option<Pointer<'ctx>> {
self.stack.insert(name, pointer)
}
/// Gets the pointer to a stack variable.
pub fn get_stack_pointer<D: Dependency + Clone>(
&self,
context: &mut Context<'ctx, D>,
name: String,
) -> Pointer<'ctx> {
let pointer_name = format!("{}_stack_pointer", &name);
let index = *self
.stack
.get(&name)
.unwrap_or_else(|| panic!("stack pointer access prior to insertion: {name}"));
let indices = &[
context.xlen_type().const_zero(),
context.xlen_type().const_int(index, false),
];
pub fn get_stack_pointer(&self, name: &str) -> Option<Pointer<'ctx>> {
self.stack.get(name).copied()
}
context.build_gep(
self.stack_variables,
indices,
context.word_type(),
&pointer_name,
)
/// Removes the pointer to a stack variable.
pub fn remove_stack_pointer(&mut self, name: &str) {
self.stack.remove(name);
}
/// Returns the return entity representation.
@@ -48,7 +48,6 @@ where
function_type,
0,
Some(inkwell::module::Linkage::External),
1024,
)?;
self.inner.declare(context)
@@ -145,7 +145,6 @@ where
entry_function_type,
0,
Some(inkwell::module::Linkage::External),
0,
)?;
context.declare_global(
@@ -48,7 +48,6 @@ where
function_type,
0,
Some(inkwell::module::Linkage::External),
1024,
)?;
self.inner.declare(context)
+5 -39
View File
@@ -247,7 +247,7 @@ where
let intrinsics = Intrinsics::new(llvm, &module);
let llvm_runtime = LLVMRuntime::new(llvm, &module, &optimizer);
let debug_info = debug_config.emit_debug_info.then(|| {
let debug_info = DebugInfo::new(&module, &debug_config);
let debug_info = DebugInfo::new(&module);
debug_info.initialize_module(llvm, &module);
debug_info
});
@@ -463,7 +463,6 @@ where
r#type: inkwell::types::FunctionType<'ctx>,
return_values_length: usize,
linkage: Option<inkwell::module::Linkage>,
stack_variables: u32,
) -> anyhow::Result<Rc<RefCell<Function<'ctx>>>> {
let value = self.module().add_function(name, r#type, linkage);
@@ -485,30 +484,15 @@ where
let entry_block = self.llvm.append_basic_block(value, "entry");
let return_block = self.llvm.append_basic_block(value, "return");
self.builder().position_at_end(entry_block);
let stack_variables_pointer = self.build_alloca(
self.word_type().array_type(stack_variables),
"stack_variables",
);
let r#return = match return_values_length {
0 => FunctionReturn::none(),
1 => {
//self.set_basic_block(entry_block);
//let pointer = self
// .current_function()
// .borrow_mut()
// .insert_stack_pointer(self, format!("{name}_return_pointer"));
FunctionReturn::primitive(self.build_gep(
stack_variables_pointer,
&[self.xlen_type().const_zero(), self.xlen_type().const_zero()],
self.word_type(),
"return_pointer",
))
self.set_basic_block(entry_block);
let pointer = self.build_alloca(self.word_type(), "return_pointer");
FunctionReturn::primitive(pointer)
}
size => {
//self.set_basic_block(entry_block);
self.set_basic_block(entry_block);
let pointer = self.build_alloca(
self.structure_type(
vec![self.word_type().as_basic_type_enum(); size].as_slice(),
@@ -525,7 +509,6 @@ where
r#return,
entry_block,
return_block,
stack_variables_pointer,
);
Function::set_default_attributes(self.llvm, function.declaration(), &self.optimizer);
let function = Rc::new(RefCell::new(function));
@@ -753,23 +736,6 @@ where
pointer
}
pub fn variable_decl<T: BasicType<'ctx> + Clone + Copy>(
&self,
r#type: T,
name: &str,
) -> Pointer<'ctx> {
let pointer = self.builder.build_alloca(r#type, name).unwrap();
pointer
.as_instruction()
.unwrap()
.set_alignment(revive_common::BYTE_LENGTH_STACK_ALIGN as u32)
.expect("Alignment is valid");
Pointer::new(r#type, AddressSpace::Stack, pointer)
}
/// Truncate `address` to the ethereum address length and store it as bytes on the stack.
/// Builds an aligned stack allocation at the current position.
/// Use this if [`build_alloca_at_entry`] might change program semantics.
/// Otherwise, alloca should always be built at the function prelude!
@@ -35,7 +35,6 @@ where
Self::r#type(context),
0,
Some(inkwell::module::Linkage::External),
0,
)?;
let mut attributes = Self::ATTRIBUTES.to_vec();
@@ -40,7 +40,6 @@ pub fn check_attribute_null_pointer_is_invalid() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -64,7 +63,6 @@ pub fn check_attribute_optimize_for_size_mode_3() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -88,7 +86,6 @@ pub fn check_attribute_optimize_for_size_mode_z() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(function
@@ -112,7 +109,6 @@ pub fn check_attribute_min_size_mode_3() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(!function
@@ -136,7 +132,6 @@ pub fn check_attribute_min_size_mode_z() {
.fn_type(&[context.word_type().into()], false),
1,
Some(inkwell::module::Linkage::External),
16,
)
.expect("Failed to add function");
assert!(function
@@ -2,13 +2,13 @@
use inkwell::values::BasicValue;
use crate::polkavm::context::runtime::RuntimeFunction;
//use crate::polkavm::context::runtime::RuntimeFunction;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
use crate::PolkaVMDivisionFunction;
use crate::PolkaVMRemainderFunction;
use crate::PolkaVMSignedDivisionFunction;
use crate::PolkaVMSignedRemainderFunction;
//use crate::PolkaVMDivisionFunction;
//use crate::PolkaVMRemainderFunction;
//use crate::PolkaVMSignedDivisionFunction;
//use crate::PolkaVMSignedRemainderFunction;
/// Translates the arithmetic addition.
pub fn addition<'ctx, D>(
@@ -64,11 +64,21 @@ pub fn division<'ctx, D>(
where
D: Dependency + Clone,
{
let name = <PolkaVMDivisionFunction as RuntimeFunction<D>>::NAME;
let declaration = <PolkaVMDivisionFunction as RuntimeFunction<D>>::declaration(context);
Ok(context
.build_call(declaration, &[operand_1.into(), operand_2.into()], "div")
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
let result_pointer = context.build_alloca_at_entry(context.word_type(), "div_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(operand_2_pointer, operand_2)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::DIV, arguments);
context.build_load(result_pointer, "div_result")
}
/// Translates the arithmetic remainder.
@@ -80,11 +90,21 @@ pub fn remainder<'ctx, D>(
where
D: Dependency + Clone,
{
let name = <PolkaVMRemainderFunction as RuntimeFunction<D>>::NAME;
let declaration = <PolkaVMRemainderFunction as RuntimeFunction<D>>::declaration(context);
Ok(context
.build_call(declaration, &[operand_1.into(), operand_2.into()], "rem")
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
let result_pointer = context.build_alloca_at_entry(context.word_type(), "rem_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(operand_2_pointer, operand_2)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::MOD, arguments);
context.build_load(result_pointer, "rem_result")
}
/// Translates the signed arithmetic division.
@@ -99,11 +119,21 @@ pub fn division_signed<'ctx, D>(
where
D: Dependency + Clone,
{
let name = <PolkaVMSignedDivisionFunction as RuntimeFunction<D>>::NAME;
let declaration = <PolkaVMSignedDivisionFunction as RuntimeFunction<D>>::declaration(context);
Ok(context
.build_call(declaration, &[operand_1.into(), operand_2.into()], "sdiv")
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
let result_pointer = context.build_alloca_at_entry(context.word_type(), "sdiv_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(operand_2_pointer, operand_2)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::SDIV, arguments);
context.build_load(result_pointer, "sdiv_result")
}
/// Translates the signed arithmetic remainder.
@@ -115,9 +145,19 @@ pub fn remainder_signed<'ctx, D>(
where
D: Dependency + Clone,
{
let name = <PolkaVMSignedRemainderFunction as RuntimeFunction<D>>::NAME;
let declaration = <PolkaVMSignedRemainderFunction as RuntimeFunction<D>>::declaration(context);
Ok(context
.build_call(declaration, &[operand_1.into(), operand_2.into()], "srem")
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
let result_pointer = context.build_alloca_at_entry(context.word_type(), "srem_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(operand_2_pointer, operand_2)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::SMOD, arguments);
context.build_load(result_pointer, "rsem_result")
}
+72 -38
View File
@@ -1,7 +1,5 @@
//! Translates the mathematical operations.
use inkwell::values::BasicValue;
use crate::polkavm::context::Context;
use crate::polkavm::Dependency;
@@ -15,17 +13,26 @@ pub fn add_mod<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context
.build_call(
context.llvm_runtime().add_mod,
&[
operand_1.as_basic_value_enum(),
operand_2.as_basic_value_enum(),
modulo.as_basic_value_enum(),
],
"add_mod_call",
)
.expect("Always exists"))
let result_pointer =
context.build_alloca_at_entry(context.word_type(), "addmod_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_1");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_2");
let modulo_pointer =
context.build_alloca_at_entry(context.word_type(), "addmod_modulo_operand");
context.build_store(operand_2_pointer, operand_2)?;
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(modulo_pointer, modulo)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
modulo_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::ADDMOD, arguments);
context.build_load(result_pointer, "addmod_result")
}
/// Translates the `mulmod` instruction.
@@ -38,17 +45,26 @@ pub fn mul_mod<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context
.build_call(
context.llvm_runtime().mul_mod,
&[
operand_1.as_basic_value_enum(),
operand_2.as_basic_value_enum(),
modulo.as_basic_value_enum(),
],
"mul_mod_call",
)
.expect("Always exists"))
let result_pointer =
context.build_alloca_at_entry(context.word_type(), "mulmod_result_pointer");
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_1");
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_2");
let modulo_pointer =
context.build_alloca_at_entry(context.word_type(), "mulmod_modulo_operand");
context.build_store(operand_2_pointer, operand_2)?;
context.build_store(operand_1_pointer, operand_1)?;
context.build_store(modulo_pointer, modulo)?;
let arguments = &[
result_pointer.to_int(context).into(),
operand_1_pointer.to_int(context).into(),
operand_2_pointer.to_int(context).into(),
modulo_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::MULMOD, arguments);
context.build_load(result_pointer, "addmod_result")
}
/// Translates the `exp` instruction.
@@ -60,13 +76,22 @@ pub fn exponent<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context
.build_call(
context.llvm_runtime().exp,
&[value.as_basic_value_enum(), exponent.as_basic_value_enum()],
"exp_call",
)
.expect("Always exists"))
let result_pointer = context.build_alloca_at_entry(context.word_type(), "exp_result_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "exp_value_pointer");
let exponent_pointer =
context.build_alloca_at_entry(context.word_type(), "exp_exponent_pointer");
context.build_store(value_pointer, value)?;
context.build_store(exponent_pointer, exponent)?;
let arguments = &[
result_pointer.to_int(context).into(),
value_pointer.to_int(context).into(),
exponent_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
context.build_load(result_pointer, "exponent_result")
}
/// Translates the `signextend` instruction.
@@ -78,11 +103,20 @@ pub fn sign_extend<'ctx, D>(
where
D: Dependency + Clone,
{
Ok(context
.build_call(
context.llvm_runtime().sign_extend,
&[bytes.as_basic_value_enum(), value.as_basic_value_enum()],
"sign_extend_call",
)
.expect("Always exists"))
let result_pointer =
context.build_alloca_at_entry(context.word_type(), "signext_result_pointer");
let bytes_pointer = context.build_alloca_at_entry(context.word_type(), "bytes_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "signext_value_pointer");
context.build_store(bytes_pointer, bytes)?;
context.build_store(value_pointer, value)?;
let arguments = &[
result_pointer.to_int(context).into(),
bytes_pointer.to_int(context).into(),
value_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
context.build_load(result_pointer, "signext_mod_result")
}
+1 -2
View File
@@ -54,7 +54,7 @@ pub fn yul<T: Compiler>(
solc: &mut T,
optimizer_settings: revive_llvm_context::OptimizerSettings,
include_metadata_hash: bool,
mut debug_config: revive_llvm_context::DebugConfig,
debug_config: revive_llvm_context::DebugConfig,
llvm_arguments: &[String],
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
) -> anyhow::Result<Build> {
@@ -77,7 +77,6 @@ pub fn yul<T: Compiler>(
let solc_validator = Some(&*solc);
let project = Project::try_from_yul_path(path, solc_validator)?;
debug_config.set_yul_path(path);
let build = project.compile(
optimizer_settings,
include_metadata_hash,
+1 -2
View File
@@ -77,7 +77,7 @@ impl Contract {
project: Project,
optimizer_settings: revive_llvm_context::OptimizerSettings,
include_metadata_hash: bool,
mut debug_config: revive_llvm_context::DebugConfig,
debug_config: revive_llvm_context::DebugConfig,
llvm_arguments: &[String],
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
) -> anyhow::Result<ContractBuild> {
@@ -117,7 +117,6 @@ impl Contract {
_ => llvm.create_module(self.path.as_str()),
};
debug_config.set_contract_path(&self.path);
let mut context = revive_llvm_context::PolkaVMContext::new(
&llvm,
module,
+3 -1
View File
@@ -45,6 +45,8 @@ impl Compiler for SolcCompiler {
include_paths: Vec<String>,
allow_paths: Option<String>,
) -> anyhow::Result<SolcStandardJsonOutput> {
let version = self.version()?.validate(&include_paths)?.default;
let mut command = std::process::Command::new(self.executable.as_str());
command.stdin(std::process::Stdio::piped());
command.stdout(std::process::Stdio::piped());
@@ -63,7 +65,7 @@ impl Compiler for SolcCompiler {
command.arg(allow_paths);
}
input.normalize();
input.normalize(&version);
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
+2 -1
View File
@@ -40,7 +40,8 @@ impl Compiler for SoljsonCompiler {
anyhow::bail!("configuring allow paths is not supported with solJson")
}
input.normalize();
let version = self.version()?.validate(&include_paths)?.default;
input.normalize(&version);
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
+16
View File
@@ -104,3 +104,19 @@ POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, ui
POLKAVM_IMPORT(void, value_transferred, uint32_t)
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
POLKAVM_IMPORT(void, div, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, sdiv, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, addmod, uint32_t, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, mulmod, uint32_t, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, mod, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, smod, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, exp, uint32_t, uint32_t, uint32_t);
POLKAVM_IMPORT(void, signext, uint32_t, uint32_t, uint32_t);
+19 -1
View File
@@ -68,9 +68,27 @@ pub static VALUE_TRANSFERRED: &str = "value_transferred";
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
pub static DIV: &str = "div";
pub static SDIV: &str = "sdiv";
pub static ADDMOD: &str = "addmod";
pub static MULMOD: &str = "mulmod";
pub static MOD: &str = "mod";
pub static SMOD: &str = "smod";
pub static EXP: &str = "exp";
pub static SIGNEXT: &str = "signext";
/// All imported runtime API symbols.
/// Useful for configuring common attributes and linkage.
pub static IMPORTS: [&str; 33] = [
pub static IMPORTS: [&str; 41] = [
DIV,
SDIV,
ADDMOD,
MULMOD,
MOD,
SMOD,
EXP,
SIGNEXT,
//
ADDRESS,
BALANCE,
BALANCE_OF,
-1
View File
@@ -7,7 +7,6 @@ pub use self::combined_json::contract::Contract as CombinedJsonContract;
pub use self::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
pub use self::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
pub use self::standard_json::input::settings::metadata_hash::MetadataHash as SolcStandardJsonInputSettingsMetadataHash;
pub use self::standard_json::input::settings::optimizer::yul_details::YulDetails as SolcStandardJsonInputSettingsYulOptimizerDetails;
pub use self::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
pub use self::standard_json::input::settings::polkavm::memory::MemoryConfig as SolcStandardJsonInputSettingsPolkaVMMemory;
pub use self::standard_json::input::settings::polkavm::memory::DEFAULT_HEAP_SIZE as PolkaVMDefaultHeapMemorySize;
@@ -140,7 +140,7 @@ impl Input {
}
/// Sets the necessary defaults.
pub fn normalize(&mut self) {
self.settings.normalize();
pub fn normalize(&mut self, version: &semver::Version) {
self.settings.normalize(version);
}
}
@@ -74,9 +74,9 @@ impl Settings {
}
/// Sets the necessary defaults.
pub fn normalize(&mut self) {
pub fn normalize(&mut self, version: &semver::Version) {
self.polkavm = None;
self.optimizer.normalize();
self.optimizer.normalize(version);
}
/// Parses the library list and returns their double hashmap with path and name as keys.
@@ -3,54 +3,37 @@
use serde::Deserialize;
use serde::Serialize;
use crate::standard_json::input::settings::optimizer::yul_details::YulDetails;
/// The `solc --standard-json` input settings optimizer details.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Details {
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub peephole: Option<bool>,
pub peephole: bool,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub inliner: Option<bool>,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub jumpdest_remover: Option<bool>,
pub jumpdest_remover: bool,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub order_literals: Option<bool>,
pub order_literals: bool,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub deduplicate: Option<bool>,
pub deduplicate: bool,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub cse: Option<bool>,
pub cse: bool,
/// Whether the pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub constant_optimizer: Option<bool>,
/// Whether the YUL optimizer is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub yul: Option<bool>,
/// The YUL optimizer configuration.
#[serde(skip_serializing_if = "Option::is_none")]
pub yul_details: Option<YulDetails>,
pub constant_optimizer: bool,
}
impl Details {
/// A shortcut constructor.
#[allow(clippy::too_many_arguments)]
pub fn new(
peephole: Option<bool>,
peephole: bool,
inliner: Option<bool>,
jumpdest_remover: Option<bool>,
order_literals: Option<bool>,
deduplicate: Option<bool>,
cse: Option<bool>,
constant_optimizer: Option<bool>,
yul: Option<bool>,
yul_details: Option<YulDetails>,
jumpdest_remover: bool,
order_literals: bool,
deduplicate: bool,
cse: bool,
constant_optimizer: bool,
) -> Self {
Self {
peephole,
@@ -60,11 +43,10 @@ impl Details {
deduplicate,
cse,
constant_optimizer,
yul,
yul_details,
}
}
/// Creates a set of disabled optimizations.
pub fn disabled(version: &semver::Version) -> Self {
let inliner = if version >= &semver::Version::new(0, 8, 5) {
Some(false)
@@ -72,16 +54,6 @@ impl Details {
None
};
Self::new(
Some(false),
inliner,
Some(false),
Some(false),
Some(false),
Some(false),
Some(false),
None,
None,
)
Self::new(false, inliner, false, false, false, false, false)
}
}
@@ -1,7 +1,6 @@
//! The `solc --standard-json` input settings optimizer.
pub mod details;
pub mod yul_details;
use serde::Deserialize;
use serde::Serialize;
@@ -42,8 +41,13 @@ impl Optimizer {
}
/// Sets the necessary defaults.
pub fn normalize(&mut self) {
pub fn normalize(&mut self, version: &semver::Version) {
self.mode = None;
self.fallback_to_optimizing_for_size = None;
self.details = if version >= &semver::Version::new(0, 5, 5) {
Some(Details::disabled(version))
} else {
None
};
}
}
@@ -1,26 +0,0 @@
//! The `solc --standard-json` input settings YUL optimizer details.
use serde::Deserialize;
use serde::Serialize;
/// The `solc --standard-json` input settings optimizer YUL details.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct YulDetails {
/// Whether the stack allocation pass is enabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub stack_allocation: Option<bool>,
/// The optimization step sequence string.
#[serde(skip_serializing_if = "Option::is_none")]
pub optimizer_steps: Option<String>,
}
impl YulDetails {
/// A shortcut constructor.
pub fn new(stack_allocation: Option<bool>, optimizer_steps: Option<String>) -> Self {
Self {
stack_allocation,
optimizer_steps,
}
}
}
+18 -4
View File
@@ -130,8 +130,15 @@ where
let identifier = self.bindings.remove(0);
let pointer = context
.current_function()
.borrow_mut()
.get_stack_pointer(context, identifier.inner.clone());
.borrow()
.get_stack_pointer(identifier.inner.as_str())
.ok_or_else(|| {
anyhow::anyhow!(
"{} Assignment to an undeclared variable `{}`",
identifier.location,
identifier.inner,
)
})?;
context.build_store(pointer, value.access(context)?)?;
return Ok(());
}
@@ -158,8 +165,15 @@ where
let binding_pointer = context
.current_function()
.borrow_mut()
.get_stack_pointer(context, binding.inner.clone());
.borrow()
.get_stack_pointer(binding.inner.as_str())
.ok_or_else(|| {
anyhow::anyhow!(
"{} Assignment to an undeclared variable `{}`",
binding.location,
binding.inner,
)
})?;
let value = context.build_load(
field_pointer,
format!("assignment_binding_{index}_value").as_str(),
@@ -123,7 +123,6 @@ impl FunctionCall {
D: revive_llvm_context::PolkaVMDependency + Clone,
{
let location = self.location;
context.set_debug_location(location.line, 0, None)?;
match self.name {
Name::UserDefined(name) => {
@@ -123,8 +123,11 @@ impl Expression {
let pointer = context
.current_function()
.borrow_mut()
.get_stack_pointer(context, id.clone());
.borrow()
.get_stack_pointer(&id)
.ok_or_else(|| {
anyhow::anyhow!("{} Undeclared variable `{}`", identifier.location, id)
})?;
let constant = context.current_function().borrow().yul().get_constant(&id);
@@ -212,7 +212,6 @@ where
function_type,
self.result.len(),
Some(inkwell::module::Linkage::External),
1024,
)?;
revive_llvm_context::PolkaVMFunction::set_attributes(
context.llvm(),
@@ -245,7 +244,7 @@ where
context
.current_function()
.borrow_mut()
.insert_stack_pointer(context, identifier.inner);
.insert_stack_pointer(identifier.inner, pointer);
}
revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. } => {
for (index, identifier) in self.result.into_iter().enumerate() {
@@ -265,24 +264,25 @@ where
context
.current_function()
.borrow_mut()
.insert_stack_pointer(context, identifier.inner.clone());
.insert_stack_pointer(identifier.inner.clone(), pointer);
}
}
};
//let argument_types: Vec<_> = self
// .arguments
// .iter()
// .map(|argument| {
// let yul_type = argument.r#type.to_owned().unwrap_or_default();
// yul_type.into_llvm(context)
// })
// .collect();
let argument_types: Vec<_> = self
.arguments
.iter()
.map(|argument| {
let yul_type = argument.r#type.to_owned().unwrap_or_default();
yul_type.into_llvm(context)
})
.collect();
for (index, argument) in self.arguments.iter().enumerate() {
let pointer = context
let pointer = context.build_alloca(argument_types[index], argument.inner.as_str());
context
.current_function()
.borrow_mut()
.insert_stack_pointer(context, argument.inner.clone());
.insert_stack_pointer(argument.inner.clone(), pointer);
context.build_store(
pointer,
context.current_function().borrow().get_nth_param(index),
@@ -53,7 +53,6 @@ where
D: revive_llvm_context::PolkaVMDependency + Clone,
{
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
context.set_debug_location(self.location.line, 0, None)?;
let condition = self
.condition
.into_llvm(context)?
+8 -8
View File
@@ -204,10 +204,10 @@ where
revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?;
revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?;
revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
revive_llvm_context::PolkaVMRemainderFunction.declare(context)?;
revive_llvm_context::PolkaVMSignedRemainderFunction.declare(context)?;
//revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
//revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
//revive_llvm_context::PolkaVMRemainderFunction.declare(context)?;
//revive_llvm_context::PolkaVMSignedRemainderFunction.declare(context)?;
revive_llvm_context::PolkaVMSbrkFunction.declare(context)?;
@@ -258,10 +258,10 @@ where
revive_llvm_context::PolkaVMEventLogFunction::<3>.into_llvm(context)?;
revive_llvm_context::PolkaVMEventLogFunction::<4>.into_llvm(context)?;
revive_llvm_context::PolkaVMDivisionFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMSignedRemainderFunction.into_llvm(context)?;
//revive_llvm_context::PolkaVMDivisionFunction.into_llvm(context)?;
//revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
//revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
//revive_llvm_context::PolkaVMSignedRemainderFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMSbrkFunction.into_llvm(context)?;
@@ -104,10 +104,11 @@ where
context.set_debug_location(self.location.line, 0, None)?;
let identifier_type = identifier.r#type.clone().unwrap_or_default();
let r#type = identifier_type.into_llvm(context);
let pointer = context
let pointer = context.build_alloca(r#type, identifier.inner.as_str());
context
.current_function()
.borrow_mut()
.insert_stack_pointer(context, identifier.inner.clone());
.insert_stack_pointer(identifier.inner.clone(), pointer);
let value = if let Some(expression) = self.expression {
match expression.into_llvm(context)? {
@@ -139,11 +140,15 @@ where
.to_owned()
.unwrap_or_default()
.into_llvm(context);
let pointer = context
let pointer = context.build_alloca(
yul_type.as_basic_type_enum(),
format!("binding_{index}_pointer").as_str(),
);
context.build_store(pointer, yul_type.const_zero())?;
context
.current_function()
.borrow_mut()
.insert_stack_pointer(context, binding.inner.to_owned());
context.build_store(pointer, yul_type.const_zero())?;
.insert_stack_pointer(binding.inner.to_owned(), pointer);
}
let expression = match self.expression.take() {
@@ -198,7 +203,14 @@ where
let pointer = context
.current_function()
.borrow_mut()
.get_stack_pointer(context, binding.inner.to_owned());
.get_stack_pointer(binding.inner.as_str())
.ok_or_else(|| {
anyhow::anyhow!(
"{} Assignment to an undeclared variable `{}`",
binding.location,
binding.inner
)
})?;
context.build_store(pointer, value)?;
}
+3 -4
View File
@@ -70,11 +70,10 @@ impl Type {
D: revive_llvm_context::PolkaVMDependency + Clone,
{
match self {
//Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
//Self::Int(bitlength) => context.integer_type(bitlength),
Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
Self::Int(bitlength) => context.integer_type(bitlength),
Self::UInt(bitlength) => context.integer_type(bitlength),
//Self::Custom(_) => context.word_type(),
_ => unreachable!("no other YUL type is supported"),
Self::Custom(_) => context.word_type(),
}
}
}