Skip to content
This repository was archived by the owner on Mar 24, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5cfcd73
Add testing against cairo runner
DomHenderson Mar 7, 2023
9c04f64
Fix negative felt wraparound
DomHenderson Mar 7, 2023
21eabb1
Switch to sierra tests rather than cairo
DomHenderson Mar 10, 2023
03c3042
Add gitignore for comparison test folder
DomHenderson Mar 10, 2023
5252de6
Retry test that couldn't reach apt.llvm.org
DomHenderson Mar 10, 2023
b83d7f5
Enum type definition
DomHenderson Mar 7, 2023
2a4f521
enum_init (TODO debg), fix packing
DomHenderson Mar 8, 2023
878e5ba
WIP data flow
DomHenderson Mar 9, 2023
e7bea44
dataflow processing and enum match
DomHenderson Mar 14, 2023
55afad3
Drop branch-specific variable in other branches
DomHenderson Mar 14, 2023
eff7984
Allow variables to be reintroduced
DomHenderson Mar 14, 2023
1f23653
Reimplemented felt_is_zero with the new data model
DomHenderson Mar 14, 2023
77d3cca
Reintroduce main function return prints
DomHenderson Mar 14, 2023
f719928
Use debug scopes
DomHenderson Mar 14, 2023
0deb9d8
Remove outdated todo
DomHenderson Mar 14, 2023
ee2bcbf
Add dataflow tests
DomHenderson Mar 14, 2023
50dc200
Fix missing compiler state checks
DomHenderson Mar 14, 2023
2b463ad
Fix debug line numbers
DomHenderson Mar 14, 2023
05d3b05
Update example ir
DomHenderson Mar 14, 2023
dc88a72
Documentation
DomHenderson Mar 14, 2023
1fd22f2
Remove leftover prints
DomHenderson Mar 15, 2023
c78d327
Remove obsolete user-func handling
DomHenderson Mar 15, 2023
6d3bc6f
Remove leftover todo comment
DomHenderson Mar 15, 2023
37318d5
Add void func test
DomHenderson Mar 15, 2023
1ee8acf
Improve debug handling of enums
DomHenderson Mar 15, 2023
9c9c10b
Test return unpacking
DomHenderson Mar 15, 2023
6565966
WIP main result printing
DomHenderson Mar 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
710 changes: 681 additions & 29 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions benches/execution.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::fs;
use std::path::Path;

Expand All @@ -13,6 +13,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use inkwell::execution_engine::ExecutionEngine;
use inkwell::OptimizationLevel;
use shenlong_core::sierra::llvm_compiler::{CompilationState, Compiler, DebugCompiler};
use shenlong_core::sierra::process::dataflow::DataFlowGraph;

pub fn criterion_benchmark(c: &mut Criterion) {
benchmark_llvm(c, "core/tests/test_data/sierra/fib_bench.sierra");
Expand Down Expand Up @@ -55,23 +56,23 @@ fn benchmark_llvm(c: &mut Criterion, file_path: &str) {
context: &context,
builder: &builder,
module,
variables: HashMap::new(),
llvm_output_path: Path::new("").to_path_buf(),
state: CompilationState::NotStarted,
valid_state_transitions: Compiler::init_state_transitions(),
types_by_id: HashMap::new(),
types_by_name: HashMap::new(),
basic_blocks: HashMap::new(),
jump_dests: HashSet::new(),
enum_packing_index_by_name: HashMap::new(),
dataflow_graph: DataFlowGraph::new(),
user_functions: HashMap::new(),
debug,
};

compiler.setup_debug().unwrap();
compiler.process_types().unwrap();
compiler.process_core_lib_functions().unwrap();
compiler.collect_jumps();
compiler.process_funcs().unwrap();
compiler.process_dataflow().unwrap();
compiler.process_statements().unwrap();
let execution_engine = compiler.module.create_jit_execution_engine(OptimizationLevel::Aggressive).unwrap();
c.bench_with_input(BenchmarkId::new("Llvm", 1), &(execution_engine), |b, execution_engine| {
b.iter(|| {
Expand Down
9 changes: 8 additions & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@ cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo", branch =
env_logger = "0.10.0"
tempdir = "0.3.7"
num-bigint = "0.4"
num-traits = "0.2.15"
thiserror = "1.0.38"
test-case = "3.0.0"
tracing = "0.1.37"
regex = "1.7.1"
num-integer = "0.1.45"
itertools = "0.10.5"

[dev-dependencies]
anyhow = "1.0.66"
cairo-lang-compiler = { git = "https://github.com/starkware-libs/cairo", branch = "main" }
cairo-lang-diagnostics = { git = "https://github.com/starkware-libs/cairo", branch = "main" }
cairo-lang-runner = { git = "https://github.com/starkware-libs/cairo", branch = "main" }
cairo-lang-sierra-generator = { git = "https://github.com/starkware-libs/cairo", branch = "main" }
pretty_assertions = "1.3.0"
proptest = "1.1.0"
tinytemplate = "1.2.1"
serde = { version = "1.0.152", features = ["derive"] }
num-bigint = "0.4.3"
num-traits = "0.2.15"
86 changes: 86 additions & 0 deletions core/src/sierra/corelib_functions/enums/enum_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use cairo_lang_sierra::ids::ConcreteTypeId;
use cairo_lang_sierra::program::{GenericArg, LibfuncDeclaration};
use num_traits::ToPrimitive;

use crate::sierra::errors::DEBUG_NAME_EXPECTED;
use crate::sierra::llvm_compiler::Compiler;

impl<'a, 'ctx> Compiler<'a, 'ctx> {
/// Implementation of the LLVM IR conversion of an enum initialisation operation.
///
/// # Arguments
///
/// * `libfunc_declaration` - The corelib function declaration of `enum_init<T>`.
///
/// # Error
///
/// Panics if the type T has not been declared previously as all types should be declared at the
/// beginning of the sierra file.
/// Panics if the sierra file doesn't have the debug infos.
pub fn enum_init(&mut self, libfunc_declaration: &LibfuncDeclaration) {
// Type of the enum that we have to construct.
let func_name = libfunc_declaration.id.debug_name.as_ref().expect(DEBUG_NAME_EXPECTED).as_str();
let (full_enum_type_id, enum_type_name) = match &libfunc_declaration.long_id.generic_args[0] {
GenericArg::Type(ConcreteTypeId { id, debug_name }) => {
(id, debug_name.clone().expect(DEBUG_NAME_EXPECTED).to_string())
}
_val => {
panic!("Enum init only takes predefined enums")
}
};
let enum_index_type_name = format!("ut@{}", enum_type_name);
let enum_index_parameter = match &libfunc_declaration.long_id.generic_args[1] {
GenericArg::Value(val) => val.to_usize().unwrap(),
_ => {
panic!("Enum init only takes predefined enums")
}
};
let enum_index_type = self.types_by_name.get(&enum_index_type_name).unwrap().into_int_type();
let return_type = self.types_by_id.get(full_enum_type_id).unwrap().into_struct_type();

// Find the location in the struct representation at which the payload is held
let data_offset = self
.enum_packing_index_by_name
.get(&enum_type_name)
.expect("Enum data packing locations should have been registered before processing of enum_init")
[enum_index_parameter];

let input_type = return_type.get_field_type_at_index(data_offset as u32).unwrap();
let debug_arg_type = self.debug.struct_types_by_id.get(full_enum_type_id).unwrap()[data_offset];
let debug_return_type = *self.debug.types_by_id.get(full_enum_type_id).unwrap();

// fn enum_init<T, i>(T[i]) -> T
// which is to say that to construct an enum we only need input for the value that's actually stored
let func = self.module.add_function(func_name, return_type.fn_type(&[input_type.into()], false), None);

let debug_func = self.debug.create_function(func_name, &func, Some(debug_return_type), &[debug_arg_type], None);

self.builder.position_at_end(self.context.append_basic_block(func, "entry"));
// Allocate memory for the enum on the stack.
let enum_ptr = self.builder.build_alloca(return_type, "res_ptr");
// Store the index in the struct
let index_to_store = enum_index_type.const_int(enum_index_parameter as u64, false);
let ptr_to_index = self.builder.build_struct_gep(return_type, enum_ptr, 0u32, "index_ptr").unwrap();
self.builder.build_store(ptr_to_index, index_to_store);
// Store the payload in the struct
let value_to_store = func.get_first_param().expect("enum_init should have one parameter");
let ptr_to_member =
self.builder.build_struct_gep(return_type, enum_ptr, data_offset as u32, "member_ptr").unwrap();
self.builder.build_store(ptr_to_member, value_to_store);

// Finally, return the enum
// Could potentially return the pointer here, likely won't make much difference though
self.builder.build_return(Some(&self.builder.build_load(return_type, enum_ptr, "res")));

// // Debug values
for (i, (value, arg_ty)) in func.get_params().iter().zip([debug_arg_type]).enumerate() {
let debug_local_var = self.debug.create_local_variable(&i.to_string(), debug_func.scope, arg_ty, None);
self.debug.insert_dbg_value(
*value,
debug_local_var,
self.builder.get_current_debug_location().unwrap(),
func.get_first_basic_block().unwrap().get_first_instruction().unwrap(),
);
}
}
}
2 changes: 2 additions & 0 deletions core/src/sierra/corelib_functions/enums/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod enum_init;
// no enum match here, handled in statements_processing
161 changes: 0 additions & 161 deletions core/src/sierra/corelib_functions/functions/function_call.rs

This file was deleted.

1 change: 0 additions & 1 deletion core/src/sierra/corelib_functions/functions/mod.rs

This file was deleted.

2 changes: 1 addition & 1 deletion core/src/sierra/corelib_functions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod boxes;
pub mod functions;
pub mod enums;
pub mod math;
pub mod memory;
pub mod structs;
Loading