Skip to content

Commit

Permalink
Renamed alloca and malloc to be closer to LLVM name
Browse files Browse the repository at this point in the history
Also added get_context for BasicBlocks.
  • Loading branch information
TheDan64 committed Oct 24, 2017
1 parent 988a128 commit 0767f25
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 10 deletions.
2 changes: 1 addition & 1 deletion examples/kaleidoscope/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ impl<'a> Compiler<'a> {
None => builder.position_at_end(entry)
}

builder.build_stack_allocation(&self.context.f64_type(), name)
builder.build_alloca(&self.context.f64_type(), name)
}

/// Compiles the specified `Expr` into an LLVM `FloatValue`.
Expand Down
11 changes: 10 additions & 1 deletion src/basic_block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMInsertBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction};
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMInsertBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction, LLVMGetTypeContext, LLVMBasicBlockAsValue};
use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};

use context::{Context, ContextRef};
use values::{FunctionValue, InstructionValue};

use std::fmt;
Expand Down Expand Up @@ -126,6 +127,14 @@ impl BasicBlock {
LLVMDeleteBasicBlock(self.basic_block)
// }
}

pub fn get_context(&self) -> ContextRef {
let context = unsafe {
LLVMGetTypeContext(LLVMTypeOf(LLVMBasicBlockAsValue(self.basic_block)))
};

ContextRef::new(Context::new(context))
}
}

impl fmt::Debug for BasicBlock {
Expand Down
18 changes: 11 additions & 7 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ impl Builder {
BasicValueEnum::new(value)
}

pub fn build_stack_allocation(&self, type_: &BasicType, name: &str) -> PointerValue {
// TODOC: Stack allocation
pub fn build_alloca(&self, type_: &BasicType, name: &str) -> PointerValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
Expand All @@ -178,31 +179,34 @@ impl Builder {
PointerValue::new(value)
}

pub fn build_heap_allocation(&self, type_: &BasicType, name: &str) -> PointerValue {
// TODOC: Stack allocation
pub fn build_array_alloca(&self, type_: &BasicType, size: &IntValue, name: &str) -> PointerValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildMalloc(self.builder, type_.as_type_ref(), c_string.as_ptr())
LLVMBuildArrayAlloca(self.builder, type_.as_type_ref(), size.as_value_ref(), c_string.as_ptr())
};

PointerValue::new(value)
}

pub fn build_heap_allocated_array(&self, type_: &BasicType, size: &IntValue, name: &str) -> PointerValue {
// TODOC: Heap allocation
pub fn build_malloc(&self, type_: &BasicType, name: &str) -> PointerValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildArrayMalloc(self.builder, type_.as_type_ref(), size.as_value_ref(), c_string.as_ptr())
LLVMBuildMalloc(self.builder, type_.as_type_ref(), c_string.as_ptr())
};

PointerValue::new(value)
}

pub fn build_stack_allocated_array(&self, type_: &BasicType, size: &IntValue, name: &str) -> PointerValue {
// TODOC: Heap allocation
pub fn build_array_malloc(&self, type_: &BasicType, size: &IntValue, name: &str) -> PointerValue {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

let value = unsafe {
LLVMBuildArrayAlloca(self.builder, type_.as_type_ref(), size.as_value_ref(), c_string.as_ptr())
LLVMBuildArrayMalloc(self.builder, type_.as_type_ref(), size.as_value_ref(), c_string.as_ptr())
};

PointerValue::new(value)
Expand Down
4 changes: 3 additions & 1 deletion src/types/traits.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use llvm_sys::prelude::LLVMTypeRef;

use std::fmt::Debug;

use types::{IntType, FunctionType, FloatType, PointerType, StructType, ArrayType, VectorType, VoidType};
use types::enums::{AnyTypeEnum, BasicTypeEnum};

Expand All @@ -12,7 +14,7 @@ pub trait AsTypeRef {

macro_rules! trait_type_set {
($trait_name:ident: $($args:ident),*) => (
pub trait $trait_name: AsTypeRef {}
pub trait $trait_name: AsTypeRef + Debug {}

$(
impl $trait_name for $args {}
Expand Down
2 changes: 2 additions & 0 deletions src/values/fn_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ impl FunctionValue {
BasicBlock::new(bb)
}

// TODOC: This applies the global context to the basic block. To keep the existing context
// prefer context.append_basic_block()
pub fn append_basic_block(&self, name: &str) -> BasicBlock {
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");

Expand Down
16 changes: 16 additions & 0 deletions tests/test_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,19 @@ fn test_get_context_from_contextless_value() {
assert_ne!(*int.get_context(), context);
assert_ne!(*global_context, context);
}

#[test]
fn test_basic_block_context() {
let context = Context::create();
let module = context.create_module("my_mod");
let void_type = context.void_type();
let fn_type = void_type.fn_type(&[], false);
let fn_value = module.add_function("my_fn", &fn_type, None);
let basic_block = fn_value.append_basic_block("entry");

assert_eq!(basic_block.get_context(), Context::get_global());

let basic_block2 = context.append_basic_block(&fn_value, "entry2");

assert_eq!(*basic_block2.get_context(), context);
}
25 changes: 25 additions & 0 deletions tests/test_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,3 +853,28 @@ fn test_phi_values() {
assert_eq!(else_bb, else_block);
assert!(phi.get_incoming(2).is_none());
}

#[test]
fn test_allocations() {
let context = Context::create();
let i32_type = context.i32_type();
let i32_three = i32_type.const_int(3, false);
let builder = context.create_builder();
let stack_ptr = builder.build_alloca(&i32_type, "stack_ptr");

assert_eq!(stack_ptr.get_type().print_to_string(), &*CString::new("i32*").unwrap());

let stack_array = builder.build_array_alloca(&i32_type, &i32_three, "stack_array");

assert_eq!(stack_array.get_type().print_to_string(), &*CString::new("i32*").unwrap());

// REVIEW: Heap allocations are not working:

// let heap_ptr = builder.build_malloc(&i32_type, "heap_ptr");

// assert_eq!(heap_ptr.get_type().print_to_string(), &*CString::new("i32*").unwrap());

// let heap_array = builder.build_array_malloc(&i32_type, &i32_three, "heap_array");

// assert_eq!(heap_array.get_type().print_to_string(), &*CString::new("i32*").unwrap());
}

0 comments on commit 0767f25

Please sign in to comment.