Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
add indexed function and corresponding module, fixes #65
Browse files Browse the repository at this point in the history
  • Loading branch information
cpdt committed Sep 18, 2018
1 parent 9562fe4 commit 605841b
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 3 deletions.
174 changes: 174 additions & 0 deletions compiler/src/codegen/functions/indexed_function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use super::{Function, FunctionContext, VarArgs};
use ast::FormType;
use codegen::values::{ArrayValue, NumValue, ARRAY_CAPACITY};
use codegen::{intrinsics, util};
use inkwell::values::PointerValue;
use inkwell::IntPredicate;
use mir::block;

pub struct IndexedFunction;
impl Function for IndexedFunction {
fn function_type() -> block::Function {
block::Function::Indexed
}

fn gen_call(
func: &mut FunctionContext,
args: &[PointerValue],
_varargs: Option<VarArgs>,
result: PointerValue,
) {
let min_intrinsic = intrinsics::minnum_f32(func.ctx.module);
let max_intrinsic = intrinsics::maxnum_f32(func.ctx.module);

let input_num = NumValue::new(args[0]);
let result_array = ArrayValue::new(result);

let input_vec = input_num.get_vec(&mut func.ctx.b);
let input_count_float = func
.ctx
.b
.build_extract_element(
&input_vec,
&func.ctx.context.i64_type().const_int(0, false),
"input.left",
)
.into_float_value();
let input_count_clamped = func
.ctx
.b
.build_call(
&min_intrinsic,
&[
&func
.ctx
.b
.build_call(
&max_intrinsic,
&[
&input_count_float,
&func.ctx.context.f32_type().const_float(0.),
],
"",
false,
)
.left()
.unwrap()
.into_float_value(),
&func
.ctx
.context
.f32_type()
.const_float(ARRAY_CAPACITY as f64),
],
"",
false,
)
.left()
.unwrap()
.into_float_value();

let input_count_int = func.ctx.b.build_float_to_unsigned_int(
input_count_clamped,
func.ctx.context.i8_type(),
"input.int",
);

// figure out the bitmap for the array
let shift_amount = func.ctx.b.build_int_nuw_sub(
func.ctx
.context
.i8_type()
.const_int(ARRAY_CAPACITY as u64, false),
input_count_int,
"shiftamount",
);

// LLVM defines shifting left by the same number of bits as the input as undefined (so we can't shift a 32-bit number 32 bits left).
// Since this will happen when the input value is 0, we do the shifting as 64-bit integers and truncate the result to 32 bits.
let bitmap = func.ctx.b.build_left_shift(
func.ctx.context.i64_type().const_int(!0u64 as u64, false),
func.ctx.b.build_int_z_extend_or_bit_cast(
shift_amount,
func.ctx.context.i64_type(),
"",
),
"",
);
let truncated_bitmap =
func.ctx
.b
.build_int_truncate(bitmap, func.ctx.context.i32_type(), "");
result_array.set_bitmap(func.ctx.b, &truncated_bitmap);

// loop through the indices to build up the output array values
let loop_index_ptr = func
.ctx
.allocb
.build_alloca(&func.ctx.context.i8_type(), "index.ptr");
func.ctx.b.build_store(
&loop_index_ptr,
&func.ctx.context.i8_type().const_int(0, false),
);

let loop_check_block = func
.ctx
.context
.append_basic_block(&func.ctx.func, "loop.check");
let loop_body_block = func
.ctx
.context
.append_basic_block(&func.ctx.func, "loop.body");
let loop_end_block = func
.ctx
.context
.append_basic_block(&func.ctx.func, "loop.end");

func.ctx.b.build_unconditional_branch(&loop_check_block);

func.ctx.b.position_at_end(&loop_check_block);
let current_index = func
.ctx
.b
.build_load(&loop_index_ptr, "index")
.into_int_value();
let loop_continue = func.ctx.b.build_int_compare(
IntPredicate::ULT,
current_index,
input_count_int,
"continue",
);
func.ctx
.b
.build_conditional_branch(&loop_continue, &loop_body_block, &loop_end_block);

func.ctx.b.position_at_end(&loop_body_block);
let next_index = func.ctx.b.build_int_nuw_add(
current_index,
func.ctx.context.i8_type().const_int(1, false),
"nextindex",
);
func.ctx.b.build_store(&loop_index_ptr, &next_index);

let index_num = NumValue::new(result_array.get_item_ptr(&mut func.ctx.b, current_index));
let index_float = func.ctx.b.build_unsigned_int_to_float(
current_index,
func.ctx.context.f32_type(),
"index.float",
);
let index_vec = util::splat_vector(func.ctx.b, index_float, "index.vec");
index_num.set_vec(&mut func.ctx.b, &index_vec);
index_num.set_form(
&mut func.ctx.b,
&func
.ctx
.context
.i8_type()
.const_int(FormType::None as u64, false),
);

func.ctx.b.build_unconditional_branch(&loop_check_block);

func.ctx.b.position_at_end(&loop_end_block);
}
}
8 changes: 6 additions & 2 deletions compiler/src/codegen/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod channel_function;
mod defer_function;
mod delay_function;
mod function_context;
mod indexed_function;
mod note_function;
mod num_function;
mod oscillator_function;
Expand Down Expand Up @@ -32,6 +33,7 @@ pub use self::biquad_filter_function::*;
pub use self::channel_function::*;
pub use self::defer_function::*;
pub use self::delay_function::*;
pub use self::indexed_function::*;
pub use self::note_function::*;
pub use self::num_function::*;
pub use self::oscillator_function::*;
Expand Down Expand Up @@ -154,7 +156,8 @@ map_functions! {
PeakBqFilter => PeakBqFilterFunction,
Note => NoteFunction,
Voices => VoicesFunction,
Channel => ChannelFunction
Channel => ChannelFunction,
Indexed => IndexedFunction
}

fn get_lifecycle_func(
Expand Down Expand Up @@ -256,7 +259,8 @@ fn build_update_func(
let data_ptr = ctx.func.get_nth_param(0).unwrap().into_pointer_value();
let return_ptr = ctx.func.get_nth_param(1).unwrap().into_pointer_value();
let has_vararg = function.var_arg().is_some();
let arg_pointers: Vec<_> = ctx.func
let arg_pointers: Vec<_> = ctx
.func
.params()
.take(if has_vararg {
ctx.func.count_params() - 1
Expand Down
1 change: 1 addition & 0 deletions compiler/src/frontend/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ impl Runtime {
// deploy the library to the JIT
let library_module = Runtime::codegen_lib(&context, &target);
optimizer.optimize_module(&library_module);
library_module.print_to_stderr();
jit.deploy(&library_module);

Runtime {
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/mir/block/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ define_functions! {
RmpOsc = "rmpOsc" func![(Num, ?Num) -> Num],
Note = "note" func![(Midi) -> Tuple(vec![Num, Num, Num, Num])],
Voices = "voices" func![(Midi, VarType::new_array(Num)) -> VarType::new_array(Midi)],
Channel = "channel" func![(Midi, Num) -> Midi]
Channel = "channel" func![(Midi, Num) -> Midi],
Indexed = "indexed" func![(Num) -> VarType::new_array(Num)]
}

#[derive(Debug, Clone)]
Expand Down
Binary file modified editor/resources/default.axl
Binary file not shown.

0 comments on commit 605841b

Please sign in to comment.