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),
|
||||
};
|
||||
|
||||
compile_ast(ast, ll_filename);
|
||||
compile_ast(ast, ll_filename, false);
|
||||
let llc_output = Command::new("llc")
|
||||
.arg("-filetype=obj")
|
||||
.arg(ll_filename)
|
||||
@ -57,7 +57,7 @@ struct CompilationData {
|
||||
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!");
|
||||
let names: VariableMap = HashMap::new();
|
||||
|
||||
@ -84,13 +84,21 @@ fn compile_ast(ast: AST, filename: &str) {
|
||||
|
||||
LLVMWrap::BuildRet(builder, value);
|
||||
|
||||
println!("Printing {} to file", filename);
|
||||
println!("Compilation process finished for {}", 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.
|
||||
LLVMWrap::DisposeBuilder(builder);
|
||||
LLVMWrap::DisposeModule(module);
|
||||
LLVMWrap::ContextDispose(context);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
trait CodeGen {
|
||||
@ -172,10 +180,8 @@ impl CodeGen for Prototype {
|
||||
function_type);
|
||||
|
||||
let function_params = LLVMWrap::GetParams(function);
|
||||
println!("Params: {:?}", function_params);
|
||||
for (index, param) in function_params.iter().enumerate() {
|
||||
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;
|
||||
|
||||
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) {
|
||||
let name = CString::new(name).unwrap();
|
||||
println!("Value: {:?}", value);
|
||||
unsafe {
|
||||
core::LLVMSetValueName(value, name.as_ptr())
|
||||
}
|
||||
@ -254,6 +253,13 @@ pub fn CountBasicBlocks(function: LLVMValueRef) -> 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 {
|
||||
let out_file = CString::new(filename).unwrap();
|
||||
unsafe { core::LLVMPrintModuleToFile(module, out_file.as_ptr(), ptr::null_mut()) }
|
||||
|
52
src/main.rs
52
src/main.rs
@ -16,7 +16,7 @@ mod parser;
|
||||
use eval::Evaluator;
|
||||
mod eval;
|
||||
|
||||
use compilation::compilation_sequence;
|
||||
use compilation::{compilation_sequence, compile_ast};
|
||||
mod compilation;
|
||||
mod llvm_wrap;
|
||||
|
||||
@ -89,6 +89,7 @@ type LineReader = linefeed::Reader<linefeed::terminal::DefaultTerminal>;
|
||||
struct Repl<'a> {
|
||||
show_tokens: bool,
|
||||
show_parse: bool,
|
||||
show_llvm_ir: bool,
|
||||
evaluator: Evaluator<'a>,
|
||||
interpreter_directive_sigil: char,
|
||||
reader: LineReader,
|
||||
@ -101,6 +102,7 @@ impl<'a> Repl<'a> {
|
||||
Repl {
|
||||
show_tokens: false,
|
||||
show_parse: false,
|
||||
show_llvm_ir: false,
|
||||
evaluator: Evaluator::new_with_opts(None, trace_evaluation),
|
||||
interpreter_directive_sigil: '.',
|
||||
reader: reader,
|
||||
@ -132,30 +134,41 @@ impl<'a> Repl<'a> {
|
||||
}
|
||||
|
||||
fn input_handler(&mut self, input: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let intermediate: Result<String, String> =
|
||||
tokenize(input)
|
||||
.map_err(|e| format!("Tokenization error: {}", e.msg))
|
||||
.and_then(
|
||||
|tokens| {
|
||||
let mut output = String::new();
|
||||
|
||||
let tokens = match tokenize(input) {
|
||||
Ok(tokens) => tokens,
|
||||
Err(err) => {
|
||||
output.push_str(&format!("Tokenization error: {}\n", err.msg));
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
if self.show_tokens {
|
||||
result.push_str(&format!("Tokens: {:?}\n", tokens));
|
||||
output.push_str(&format!("Tokens: {:?}\n", tokens));
|
||||
}
|
||||
parse(&tokens, &[]).map_err(|e| format!("Parse error: {}", e.msg))
|
||||
})
|
||||
.and_then(
|
||||
|ast| {
|
||||
|
||||
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 {
|
||||
result.push_str(&format!("AST: {:?}\n", ast));
|
||||
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);
|
||||
Ok(full_output.pop().unwrap_or("".to_string()))
|
||||
});
|
||||
match intermediate {
|
||||
Ok(s) | Err(s) => result.push_str(&s),
|
||||
};
|
||||
result
|
||||
output.push_str(&full_output.pop().unwrap_or("".to_string()));
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn handle_interpreter_directive(&mut self, input: &str) -> bool {
|
||||
@ -197,6 +210,7 @@ impl<'a> Repl<'a> {
|
||||
"tokens" => self.show_tokens = show,
|
||||
"parse" => self.show_parse = show,
|
||||
"eval" => self.evaluator.trace_evaluation = show,
|
||||
"llvm" => self.show_llvm_ir = show,
|
||||
e => {
|
||||
println!("Bad `show`/`hide` argument: {}", e);
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user