Show/hide LLVM IR in REPL
This commit is contained in:
parent
2681dbc4f2
commit
bdd6f75cf6
@ -20,7 +20,7 @@ pub fn compilation_sequence(ast: AST, sourcefile: &str) {
|
|||||||
_ => panic!("Bad filename {}", sourcefile),
|
_ => panic!("Bad filename {}", sourcefile),
|
||||||
};
|
};
|
||||||
|
|
||||||
compile_ast(ast, ll_filename);
|
compile_ast(ast, ll_filename, false);
|
||||||
let llc_output = Command::new("llc")
|
let llc_output = Command::new("llc")
|
||||||
.arg("-filetype=obj")
|
.arg("-filetype=obj")
|
||||||
.arg(ll_filename)
|
.arg(ll_filename)
|
||||||
@ -57,7 +57,7 @@ struct CompilationData {
|
|||||||
main_function: LLVMValueRef,
|
main_function: LLVMValueRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_ast(ast: AST, filename: &str) {
|
pub fn compile_ast(ast: AST, filename: &str, return_string: bool) -> Option<String> {
|
||||||
println!("Compiling!");
|
println!("Compiling!");
|
||||||
let names: VariableMap = HashMap::new();
|
let names: VariableMap = HashMap::new();
|
||||||
|
|
||||||
@ -84,13 +84,21 @@ fn compile_ast(ast: AST, filename: &str) {
|
|||||||
|
|
||||||
LLVMWrap::BuildRet(builder, value);
|
LLVMWrap::BuildRet(builder, value);
|
||||||
|
|
||||||
println!("Printing {} to file", filename);
|
println!("Compilation process finished for {}", filename);
|
||||||
LLVMWrap::PrintModuleToFile(module, filename);
|
let ret = if return_string {
|
||||||
|
let s = LLVMWrap::PrintModuleToString(module);
|
||||||
|
Some(s)
|
||||||
|
} else {
|
||||||
|
LLVMWrap::PrintModuleToFile(module, filename);
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Clean up. Values created in the context mostly get cleaned up there.
|
// Clean up. Values created in the context mostly get cleaned up there.
|
||||||
LLVMWrap::DisposeBuilder(builder);
|
LLVMWrap::DisposeBuilder(builder);
|
||||||
LLVMWrap::DisposeModule(module);
|
LLVMWrap::DisposeModule(module);
|
||||||
LLVMWrap::ContextDispose(context);
|
LLVMWrap::ContextDispose(context);
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CodeGen {
|
trait CodeGen {
|
||||||
@ -172,10 +180,8 @@ impl CodeGen for Prototype {
|
|||||||
function_type);
|
function_type);
|
||||||
|
|
||||||
let function_params = LLVMWrap::GetParams(function);
|
let function_params = LLVMWrap::GetParams(function);
|
||||||
println!("Params: {:?}", function_params);
|
|
||||||
for (index, param) in function_params.iter().enumerate() {
|
for (index, param) in function_params.iter().enumerate() {
|
||||||
let name = self.parameters.get(index).expect(&format!("Failed this check at index {}", index));
|
let name = self.parameters.get(index).expect(&format!("Failed this check at index {}", index));
|
||||||
println!("Gonna set value name for : {}, value is {:?}", name, param);
|
|
||||||
let new = *param;
|
let new = *param;
|
||||||
|
|
||||||
LLVMWrap::SetValueName(new, name);
|
LLVMWrap::SetValueName(new, name);
|
||||||
|
@ -178,7 +178,6 @@ pub fn AddIncoming(phi: LLVMValueRef, incoming_values: *mut LLVMValueRef, incomi
|
|||||||
|
|
||||||
pub fn SetValueName(value: LLVMValueRef, name: &str) {
|
pub fn SetValueName(value: LLVMValueRef, name: &str) {
|
||||||
let name = CString::new(name).unwrap();
|
let name = CString::new(name).unwrap();
|
||||||
println!("Value: {:?}", value);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::LLVMSetValueName(value, name.as_ptr())
|
core::LLVMSetValueName(value, name.as_ptr())
|
||||||
}
|
}
|
||||||
@ -254,6 +253,13 @@ pub fn CountBasicBlocks(function: LLVMValueRef) -> usize {
|
|||||||
unsafe { core::LLVMCountBasicBlocks(function) as usize }
|
unsafe { core::LLVMCountBasicBlocks(function) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn PrintModuleToString(module: LLVMModuleRef) -> String {
|
||||||
|
unsafe {
|
||||||
|
let str_ptr: *const c_char = core::LLVMPrintModuleToString(module);
|
||||||
|
CStr::from_ptr(str_ptr).to_string_lossy().into_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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()) }
|
||||||
|
62
src/main.rs
62
src/main.rs
@ -16,7 +16,7 @@ mod parser;
|
|||||||
use eval::Evaluator;
|
use eval::Evaluator;
|
||||||
mod eval;
|
mod eval;
|
||||||
|
|
||||||
use compilation::compilation_sequence;
|
use compilation::{compilation_sequence, compile_ast};
|
||||||
mod compilation;
|
mod compilation;
|
||||||
mod llvm_wrap;
|
mod llvm_wrap;
|
||||||
|
|
||||||
@ -89,6 +89,7 @@ type LineReader = linefeed::Reader<linefeed::terminal::DefaultTerminal>;
|
|||||||
struct Repl<'a> {
|
struct Repl<'a> {
|
||||||
show_tokens: bool,
|
show_tokens: bool,
|
||||||
show_parse: bool,
|
show_parse: bool,
|
||||||
|
show_llvm_ir: bool,
|
||||||
evaluator: Evaluator<'a>,
|
evaluator: Evaluator<'a>,
|
||||||
interpreter_directive_sigil: char,
|
interpreter_directive_sigil: char,
|
||||||
reader: LineReader,
|
reader: LineReader,
|
||||||
@ -101,6 +102,7 @@ impl<'a> Repl<'a> {
|
|||||||
Repl {
|
Repl {
|
||||||
show_tokens: false,
|
show_tokens: false,
|
||||||
show_parse: false,
|
show_parse: false,
|
||||||
|
show_llvm_ir: false,
|
||||||
evaluator: Evaluator::new_with_opts(None, trace_evaluation),
|
evaluator: Evaluator::new_with_opts(None, trace_evaluation),
|
||||||
interpreter_directive_sigil: '.',
|
interpreter_directive_sigil: '.',
|
||||||
reader: reader,
|
reader: reader,
|
||||||
@ -132,30 +134,41 @@ impl<'a> Repl<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn input_handler(&mut self, input: &str) -> String {
|
fn input_handler(&mut self, input: &str) -> String {
|
||||||
let mut result = String::new();
|
let mut output = String::new();
|
||||||
let intermediate: Result<String, String> =
|
|
||||||
tokenize(input)
|
let tokens = match tokenize(input) {
|
||||||
.map_err(|e| format!("Tokenization error: {}", e.msg))
|
Ok(tokens) => tokens,
|
||||||
.and_then(
|
Err(err) => {
|
||||||
|tokens| {
|
output.push_str(&format!("Tokenization error: {}\n", err.msg));
|
||||||
if self.show_tokens {
|
return output;
|
||||||
result.push_str(&format!("Tokens: {:?}\n", tokens));
|
}
|
||||||
}
|
|
||||||
parse(&tokens, &[]).map_err(|e| format!("Parse error: {}", e.msg))
|
|
||||||
})
|
|
||||||
.and_then(
|
|
||||||
|ast| {
|
|
||||||
if self.show_parse {
|
|
||||||
result.push_str(&format!("AST: {:?}\n", ast));
|
|
||||||
}
|
|
||||||
// for now only handle last output
|
|
||||||
let mut full_output: Vec<String> = self.evaluator.run(ast);
|
|
||||||
Ok(full_output.pop().unwrap_or("".to_string()))
|
|
||||||
});
|
|
||||||
match intermediate {
|
|
||||||
Ok(s) | Err(s) => result.push_str(&s),
|
|
||||||
};
|
};
|
||||||
result
|
|
||||||
|
if self.show_tokens {
|
||||||
|
output.push_str(&format!("Tokens: {:?}\n", tokens));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ast = match parse(&tokens, &[]) {
|
||||||
|
Ok(ast) => ast,
|
||||||
|
Err(err) => {
|
||||||
|
output.push_str(&format!("Parse error: {:?}\n", err.msg));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.show_parse {
|
||||||
|
output.push_str(&format!("AST: {:?}\n", ast));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.show_llvm_ir {
|
||||||
|
let s = compile_ast(ast, "«repl llvm»", true).unwrap();
|
||||||
|
output.push_str(&s);
|
||||||
|
} else {
|
||||||
|
// for now only handle last output
|
||||||
|
let mut full_output: Vec<String> = self.evaluator.run(ast);
|
||||||
|
output.push_str(&full_output.pop().unwrap_or("".to_string()));
|
||||||
|
}
|
||||||
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_interpreter_directive(&mut self, input: &str) -> bool {
|
fn handle_interpreter_directive(&mut self, input: &str) -> bool {
|
||||||
@ -197,6 +210,7 @@ impl<'a> Repl<'a> {
|
|||||||
"tokens" => self.show_tokens = show,
|
"tokens" => self.show_tokens = show,
|
||||||
"parse" => self.show_parse = show,
|
"parse" => self.show_parse = show,
|
||||||
"eval" => self.evaluator.trace_evaluation = show,
|
"eval" => self.evaluator.trace_evaluation = show,
|
||||||
|
"llvm" => self.show_llvm_ir = show,
|
||||||
e => {
|
e => {
|
||||||
println!("Bad `show`/`hide` argument: {}", e);
|
println!("Bad `show`/`hide` argument: {}", e);
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user