Continuing work on phi nodes

This commit is contained in:
greg 2017-01-17 10:41:50 -08:00
parent 1702163478
commit d5f01a7b1f
2 changed files with 56 additions and 11 deletions

View File

@ -55,6 +55,7 @@ struct CompilationData {
builder: LLVMBuilderRef, builder: LLVMBuilderRef,
variables: VariableMap, variables: VariableMap,
main_function: LLVMValueRef, main_function: LLVMValueRef,
current_function: Option<LLVMValueRef>,
} }
pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option<String> { pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option<String> {
@ -75,6 +76,7 @@ pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option<Stri
module: module, module: module,
variables: names, variables: names,
main_function: main_function, main_function: main_function,
current_function: None,
}; };
let bb = LLVMWrap::AppendBasicBlockInContext(data.context, data.main_function, "entry"); let bb = LLVMWrap::AppendBasicBlockInContext(data.context, data.main_function, "entry");
@ -135,6 +137,8 @@ impl CodeGen for Function {
let function = self.prototype.codegen(data); let function = self.prototype.codegen(data);
let ref body = self.body; let ref body = self.body;
data.current_function = Some(function);
let return_type = LLVMWrap::Int64TypeInContext(data.context); let return_type = LLVMWrap::Int64TypeInContext(data.context);
let mut ret = LLVMWrap::ConstInt(return_type, 0, false); let mut ret = LLVMWrap::ConstInt(return_type, 0, false);
@ -156,6 +160,9 @@ impl CodeGen for Function {
// get basic block of main // get basic block of main
let main_bb = LLVMWrap::GetBasicBlocks(data.main_function).get(0).expect("Couldn't get first block of main").clone(); let main_bb = LLVMWrap::GetBasicBlocks(data.main_function).get(0).expect("Couldn't get first block of main").clone();
LLVMWrap::PositionBuilderAtEnd(data.builder, main_bb); LLVMWrap::PositionBuilderAtEnd(data.builder, main_bb);
data.current_function = None;
ret ret
} }
} }
@ -169,7 +176,7 @@ impl CodeGen for Prototype {
for _ in 0..num_args { for _ in 0..num_args {
arguments.push(LLVMWrap::Int64TypeInContext(data.context)); arguments.push(LLVMWrap::Int64TypeInContext(data.context));
} }
let function_type = let function_type =
LLVMWrap::FunctionType(return_type, LLVMWrap::FunctionType(return_type,
arguments, arguments,
@ -221,39 +228,53 @@ impl CodeGen for Expression {
int_value int_value
} }
Conditional(ref test, ref then_expr, ref else_expr) => { Conditional(ref test, ref then_expr, ref else_expr) => {
/*
let condition_value = test.codegen(data); let condition_value = test.codegen(data);
let is_nonzero = let is_nonzero =
LLVMWrap::BuildICmp(data.builder, LLVMWrap::BuildICmp(data.builder,
LLVMIntPredicate::LLVMIntNE, LLVMIntPredicate::LLVMIntNE,
condition_value, condition_value,
zero, zero,
"is_nonzero"); "ifcond");
let func: LLVMValueRef = data.main_function; let func = LLVMWrap::GetBasicBlockParent(LLVMWrap::GetInsertBlock(data.builder));
let then_block =
LLVMWrap::AppendBasicBlockInContext(data.context, func, "entry"); let mut then_block =
let else_block = LLVMWrap::AppendBasicBlockInContext(data.context, func, "then_block");
LLVMWrap::AppendBasicBlockInContext(data.context, func, "entry"); let mut else_block =
LLVMWrap::AppendBasicBlockInContext(data.context, func, "else_block");
let merge_block = let merge_block =
LLVMWrap::AppendBasicBlockInContext(data.context, func, "entry"); LLVMWrap::AppendBasicBlockInContext(data.context, func, "ifcont");
// add conditional branch to ifcond block
LLVMWrap::BuildCondBr(data.builder, is_nonzero, then_block, else_block); LLVMWrap::BuildCondBr(data.builder, is_nonzero, then_block, else_block);
// start inserting into then block
LLVMWrap::PositionBuilderAtEnd(data.builder, then_block); LLVMWrap::PositionBuilderAtEnd(data.builder, then_block);
// then-block codegen
let then_return = then_expr.codegen(data); let then_return = then_expr.codegen(data);
LLVMWrap::BuildBr(data.builder, merge_block); LLVMWrap::BuildBr(data.builder, merge_block);
// update then block b/c recursive codegen() call may have changed the notion of
// the current block
then_block = LLVMWrap::GetInsertBlock(data.builder);
// then do the same stuff again for the else branch
//
LLVMWrap::PositionBuilderAtEnd(data.builder, else_block); LLVMWrap::PositionBuilderAtEnd(data.builder, else_block);
let else_return = match *else_expr { let else_return = match *else_expr {
Some(ref e) => e.codegen(data), Some(ref e) => e.codegen(data),
None => zero, None => zero,
}; };
LLVMWrap::BuildBr(data.builder, merge_block); LLVMWrap::BuildBr(data.builder, merge_block);
else_block = LLVMWrap::GetInsertBlock(data.builder);
LLVMWrap::PositionBuilderAtEnd(data.builder, merge_block); LLVMWrap::PositionBuilderAtEnd(data.builder, merge_block);
let phi = LLVMWrap::BuildPhi(data.builder, int_type, "phinnode");
zero zero
*/
unreachable!()
} }
Block(ref exprs) => { Block(ref exprs) => {
let mut ret = zero; let mut ret = zero;

View File

@ -239,6 +239,10 @@ pub fn BuildICmp(builder: LLVMBuilderRef,
unsafe { core::LLVMBuildICmp(builder, op, lhs, rhs, name.as_ptr()) } unsafe { core::LLVMBuildICmp(builder, op, lhs, rhs, name.as_ptr()) }
} }
pub fn GetBasicBlockParent(block: LLVMBasicBlockRef) -> LLVMValueRef {
unsafe { core::LLVMGetBasicBlockParent(block) }
}
pub fn GetBasicBlocks(function: LLVMValueRef) -> Vec<LLVMBasicBlockRef> { pub fn GetBasicBlocks(function: LLVMValueRef) -> Vec<LLVMBasicBlockRef> {
let size = CountBasicBlocks(function); let size = CountBasicBlocks(function);
unsafe { unsafe {
@ -260,6 +264,26 @@ pub fn PrintModuleToString(module: LLVMModuleRef) -> String {
} }
} }
pub fn BuildPhi(builder: LLVMBuilderRef, ty: LLVMTypeRef, name: &str) -> LLVMValueRef {
unsafe {
let name = CString::new(name).unwrap();
unsafe { core::LLVMBuildPhi(builder, ty, name.as_ptr()) }
}
}
pub fn AddIncoming(phi_node: LLVMValueRef, incoming_values: Vec<LLVMValueRef>,
incoming_blocks: Vec<LLVMBasicBlockRef>) {
let count = incoming_blocks.len();
if incoming_values.len() != count {
panic!("Bad invocation of AddIncoming");
}
unsafe {
//core::LLVMAddIncoming(phi_node);
}
}
pub fn PrintModuleToFile(module: LLVMModuleRef, filename: &str) -> LLVMBool { pub fn PrintModuleToFile(module: LLVMModuleRef, filename: &str) -> LLVMBool {
let out_file = CString::new(filename).unwrap(); let out_file = CString::new(filename).unwrap();
unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) } unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) }