Add debug information compilation for subprograms and their parameters
This commit is contained in:
parent
9bb4f97e6b
commit
0c6d9885ec
@ -4,9 +4,9 @@ fn main() {
|
|||||||
use ConstValue::*;
|
use ConstValue::*;
|
||||||
use Instr::*;
|
use Instr::*;
|
||||||
|
|
||||||
let context = Context::new();
|
let context = Context::new("libtest");
|
||||||
|
|
||||||
let mut module = context.module("test", true);
|
let module = context.module("test", true);
|
||||||
|
|
||||||
let main = module.function("main", Type::I32, Vec::new(), FunctionFlags::default());
|
let main = module.function("main", Type::I32, Vec::new(), FunctionFlags::default());
|
||||||
let mut m_entry = main.block("entry");
|
let mut m_entry = main.block("entry");
|
||||||
|
@ -8,6 +8,7 @@ use crate::{
|
|||||||
TerminatorKind, Type, TypeData,
|
TerminatorKind, Type, TypeData,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
||||||
|
DebugSubprogramValue,
|
||||||
},
|
},
|
||||||
util::match_types,
|
util::match_types,
|
||||||
};
|
};
|
||||||
@ -65,12 +66,14 @@ pub struct InstructionHolder {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct Builder {
|
pub(crate) struct Builder {
|
||||||
modules: Rc<RefCell<Vec<ModuleHolder>>>,
|
modules: Rc<RefCell<Vec<ModuleHolder>>>,
|
||||||
|
pub(crate) producer: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn new() -> Builder {
|
pub fn new(producer: String) -> Builder {
|
||||||
Builder {
|
Builder {
|
||||||
modules: Rc::new(RefCell::new(Vec::new())),
|
modules: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
producer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,16 +196,16 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn add_function_metadata(
|
pub(crate) unsafe fn set_debug_subprogram(
|
||||||
&self,
|
&self,
|
||||||
value: &FunctionValue,
|
value: &FunctionValue,
|
||||||
metadata: DebugMetadataValue,
|
subprogram: DebugSubprogramValue,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(value.0.0);
|
let module = modules.get_unchecked_mut(value.0.0);
|
||||||
let function = module.functions.get_unchecked_mut(value.1);
|
let function = module.functions.get_unchecked_mut(value.1);
|
||||||
function.data.meta = Some(metadata)
|
function.data.debug = Some(subprogram)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use llvm_sys::{
|
|||||||
LLVMIntPredicate, LLVMLinkage,
|
LLVMIntPredicate, LLVMLinkage,
|
||||||
analysis::LLVMVerifyModule,
|
analysis::LLVMVerifyModule,
|
||||||
core::*,
|
core::*,
|
||||||
|
debuginfo::*,
|
||||||
linker::LLVMLinkModules2,
|
linker::LLVMLinkModules2,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
target::{
|
target::{
|
||||||
@ -23,6 +24,7 @@ use llvm_sys::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
CustomTypeKind,
|
CustomTypeKind,
|
||||||
builder::{TypeHolder, TypeValue},
|
builder::{TypeHolder, TypeValue},
|
||||||
|
debug_information::*,
|
||||||
util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring},
|
util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,12 +182,34 @@ pub struct LLVMModule<'a> {
|
|||||||
blocks: HashMap<BlockValue, LLVMBasicBlockRef>,
|
blocks: HashMap<BlockValue, LLVMBasicBlockRef>,
|
||||||
values: HashMap<InstructionValue, LLVMValue>,
|
values: HashMap<InstructionValue, LLVMValue>,
|
||||||
types: HashMap<TypeValue, LLVMTypeRef>,
|
types: HashMap<TypeValue, LLVMTypeRef>,
|
||||||
|
debug: Option<LLVMDebugInformation<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for LLVMModule<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(LLVMDebugInformation { builder, .. }) = self.debug {
|
||||||
|
unsafe {
|
||||||
|
LLVMDisposeDIBuilder(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LLVMDebugInformation<'a> {
|
||||||
|
debug: &'a DebugInformation,
|
||||||
|
builder: LLVMDIBuilderRef,
|
||||||
|
file_ref: LLVMMetadataRef,
|
||||||
|
scopes: &'a HashMap<DebugScopeValue, LLVMMetadataRef>,
|
||||||
|
types: &'a mut HashMap<DebugTypeValue, LLVMMetadataRef>,
|
||||||
|
subprograms: &'a mut HashMap<DebugSubprogramValue, LLVMMetadataRef>,
|
||||||
|
metadata: &'a mut HashMap<DebugMetadataValue, LLVMMetadataRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LLVMFunction {
|
pub struct LLVMFunction {
|
||||||
type_ref: LLVMTypeRef,
|
type_ref: LLVMTypeRef,
|
||||||
value_ref: LLVMValueRef,
|
value_ref: LLVMValueRef,
|
||||||
|
metadata: Option<LLVMMetadataRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LLVMValue {
|
pub struct LLVMValue {
|
||||||
@ -203,6 +227,80 @@ impl ModuleHolder {
|
|||||||
|
|
||||||
// Compile the contents
|
// Compile the contents
|
||||||
|
|
||||||
|
let mut scopes = HashMap::new();
|
||||||
|
let mut types = HashMap::new();
|
||||||
|
let mut metadata = HashMap::new();
|
||||||
|
let mut subprograms = HashMap::new();
|
||||||
|
|
||||||
|
let mut debug = if let Some(debug) = &self.debug_information {
|
||||||
|
let di_builder = LLVMCreateDIBuilder(module_ref);
|
||||||
|
|
||||||
|
let file_ref = LLVMDIBuilderCreateFile(
|
||||||
|
di_builder,
|
||||||
|
into_cstring(debug.file.name.clone()).as_ptr(),
|
||||||
|
debug.file.name.len(),
|
||||||
|
into_cstring(debug.file.directory.clone()).as_ptr(),
|
||||||
|
debug.file.directory.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let flags = String::new();
|
||||||
|
|
||||||
|
let compile_unit = LLVMDIBuilderCreateCompileUnit(
|
||||||
|
di_builder,
|
||||||
|
LLVMDWARFSourceLanguage::LLVMDWARFSourceLanguageC,
|
||||||
|
file_ref,
|
||||||
|
into_cstring(builder.producer.clone()).as_ptr(),
|
||||||
|
builder.producer.len(),
|
||||||
|
// is optimized
|
||||||
|
0,
|
||||||
|
into_cstring(flags.clone()).as_ptr(),
|
||||||
|
flags.len(),
|
||||||
|
// Runtime version
|
||||||
|
0,
|
||||||
|
// Split filename
|
||||||
|
into_cstring(debug.file.name.clone()).as_ptr(),
|
||||||
|
debug.file.name.len(),
|
||||||
|
LLVMDWARFEmissionKind::LLVMDWARFEmissionKindFull,
|
||||||
|
// The DWOId if this is a split skeleton compile unit.
|
||||||
|
0,
|
||||||
|
// Whether to emit inline debug info.
|
||||||
|
true as i32,
|
||||||
|
// Whether to emit extra debug info for
|
||||||
|
// profile collection.
|
||||||
|
false as i32,
|
||||||
|
// The clang system root (value of -isysroot).
|
||||||
|
c"".as_ptr(),
|
||||||
|
0,
|
||||||
|
// The SDK name. On Darwin, this is the last component of
|
||||||
|
// the sysroot.
|
||||||
|
c"".as_ptr(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let scope = debug.get_scopes();
|
||||||
|
scope
|
||||||
|
.borrow()
|
||||||
|
.compile_scope(compile_unit, file_ref, &mut scopes, di_builder);
|
||||||
|
|
||||||
|
let debug = LLVMDebugInformation {
|
||||||
|
builder: di_builder,
|
||||||
|
debug: debug,
|
||||||
|
file_ref,
|
||||||
|
types: &mut types,
|
||||||
|
metadata: &mut metadata,
|
||||||
|
subprograms: &mut subprograms,
|
||||||
|
scopes: &scopes,
|
||||||
|
};
|
||||||
|
|
||||||
|
for ty in debug.debug.get_types().borrow().iter() {
|
||||||
|
let meta_ref = ty.compile_debug(&debug);
|
||||||
|
debug.types.insert(ty.value.clone(), meta_ref);
|
||||||
|
}
|
||||||
|
Some(debug)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let mut types = HashMap::new();
|
let mut types = HashMap::new();
|
||||||
for ty in &self.types {
|
for ty in &self.types {
|
||||||
types.insert(ty.value, ty.compile_type(context, &types));
|
types.insert(ty.value, ty.compile_type(context, &types));
|
||||||
@ -212,10 +310,17 @@ impl ModuleHolder {
|
|||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
functions.insert(
|
functions.insert(
|
||||||
function.value,
|
function.value,
|
||||||
function.compile_signature(context, module_ref, &types),
|
function.compile_signature(context, module_ref, &types, &debug),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if let Some(debug) = &mut debug {
|
||||||
|
// for subprogram in debug.debug.get_subprograms().borrow().iter() {
|
||||||
|
// let meta_ref = subprogram.compile_debug(&functions, &debug);
|
||||||
|
// debug.subprograms.insert(subprogram.value.clone(), meta_ref);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
let mut module = LLVMModule {
|
let mut module = LLVMModule {
|
||||||
builder,
|
builder,
|
||||||
context_ref: context.context_ref,
|
context_ref: context.context_ref,
|
||||||
@ -225,17 +330,111 @@ impl ModuleHolder {
|
|||||||
types,
|
types,
|
||||||
blocks: HashMap::new(),
|
blocks: HashMap::new(),
|
||||||
values: HashMap::new(),
|
values: HashMap::new(),
|
||||||
|
debug,
|
||||||
};
|
};
|
||||||
|
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
function.compile(&mut module, self.data.is_main);
|
function.compile(&mut module, self.data.is_main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(debug) = &module.debug {
|
||||||
|
LLVMDIBuilderFinalize(debug.builder);
|
||||||
|
}
|
||||||
|
|
||||||
module_ref
|
module_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DebugScopeHolder {
|
||||||
|
unsafe fn compile_scope(
|
||||||
|
&self,
|
||||||
|
parent: LLVMMetadataRef,
|
||||||
|
file: LLVMMetadataRef,
|
||||||
|
map: &mut HashMap<DebugScopeValue, LLVMMetadataRef>,
|
||||||
|
di_builder: LLVMDIBuilderRef,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
let scope = if let Some(location) = &self.location {
|
||||||
|
LLVMDIBuilderCreateLexicalBlock(
|
||||||
|
di_builder,
|
||||||
|
parent,
|
||||||
|
file,
|
||||||
|
location.line,
|
||||||
|
location.column,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
for inner in &self.inner_scopes {
|
||||||
|
inner.compile_scope(scope, file, map, di_builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.insert(self.value.clone(), scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugMetadataHolder {
|
||||||
|
unsafe fn compile_meta(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
|
||||||
|
unsafe {
|
||||||
|
match &self.data {
|
||||||
|
DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable(
|
||||||
|
debug.builder,
|
||||||
|
*debug.scopes.get(&self.scope).unwrap(),
|
||||||
|
into_cstring(param.name.clone()).as_ptr(),
|
||||||
|
param.name.len(),
|
||||||
|
param.arg_idx,
|
||||||
|
debug.file_ref,
|
||||||
|
param.location.line,
|
||||||
|
*debug.types.get(¶m.ty).unwrap(),
|
||||||
|
param.always_preserve as i32,
|
||||||
|
param.flags.as_llvm(),
|
||||||
|
),
|
||||||
|
DebugMetadata::LocalVar(debug_local_variable) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugTypeHolder {
|
||||||
|
unsafe fn compile_debug(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
|
||||||
|
unsafe {
|
||||||
|
match &self.data {
|
||||||
|
DebugTypeData::Basic(ty) => LLVMDIBuilderCreateBasicType(
|
||||||
|
debug.builder,
|
||||||
|
into_cstring(ty.name.clone()).as_ptr(),
|
||||||
|
ty.name.len(),
|
||||||
|
ty.size_bits as u64,
|
||||||
|
ty.encoding as u32,
|
||||||
|
ty.flags.as_llvm(),
|
||||||
|
),
|
||||||
|
DebugTypeData::Subprogram(subprogram) => {
|
||||||
|
let mut params = subprogram
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.map(|p| *debug.types.get(p).unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
LLVMDIBuilderCreateSubroutineType(
|
||||||
|
debug.builder,
|
||||||
|
debug.file_ref,
|
||||||
|
params.as_mut_ptr(),
|
||||||
|
params.len() as u32,
|
||||||
|
subprogram.flags.as_llvm(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DwarfFlags {
|
||||||
|
pub fn as_llvm(&self) -> i32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TypeHolder {
|
impl TypeHolder {
|
||||||
unsafe fn compile_type(
|
unsafe fn compile_type(
|
||||||
&self,
|
&self,
|
||||||
@ -268,6 +467,7 @@ impl FunctionHolder {
|
|||||||
context: &LLVMContext,
|
context: &LLVMContext,
|
||||||
module_ref: LLVMModuleRef,
|
module_ref: LLVMModuleRef,
|
||||||
types: &HashMap<TypeValue, LLVMTypeRef>,
|
types: &HashMap<TypeValue, LLVMTypeRef>,
|
||||||
|
debug: &Option<LLVMDebugInformation>,
|
||||||
) -> LLVMFunction {
|
) -> LLVMFunction {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ret_type = self.data.ret.as_llvm(context.context_ref, types);
|
let ret_type = self.data.ret.as_llvm(context.context_ref, types);
|
||||||
@ -285,9 +485,41 @@ impl FunctionHolder {
|
|||||||
let function_ref =
|
let function_ref =
|
||||||
LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type);
|
LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type);
|
||||||
|
|
||||||
|
let metadata = if let Some(debug) = debug {
|
||||||
|
if let Some(value) = &self.data.debug {
|
||||||
|
let subprogram = debug.debug.get_subprogram_data(&value);
|
||||||
|
|
||||||
|
let mangled_length_ptr = &mut 0;
|
||||||
|
let mangled_name = LLVMGetValueName2(function_ref, mangled_length_ptr);
|
||||||
|
let mangled_length = *mangled_length_ptr;
|
||||||
|
|
||||||
|
Some(LLVMDIBuilderCreateFunction(
|
||||||
|
debug.builder,
|
||||||
|
*debug.scopes.get(&subprogram.scope).unwrap(),
|
||||||
|
into_cstring(subprogram.name.clone()).as_ptr(),
|
||||||
|
subprogram.name.clone().len(),
|
||||||
|
mangled_name,
|
||||||
|
mangled_length,
|
||||||
|
debug.file_ref,
|
||||||
|
subprogram.location.line,
|
||||||
|
*debug.types.get(&subprogram.ty).unwrap(),
|
||||||
|
subprogram.opts.is_local as i32,
|
||||||
|
subprogram.opts.is_definition as i32,
|
||||||
|
subprogram.opts.scope_line,
|
||||||
|
subprogram.opts.flags.as_llvm(),
|
||||||
|
subprogram.opts.is_optimized as i32,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
LLVMFunction {
|
LLVMFunction {
|
||||||
type_ref: fn_type,
|
type_ref: fn_type,
|
||||||
value_ref: function_ref,
|
value_ref: function_ref,
|
||||||
|
metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,15 @@ pub struct DebugScopeValue(pub Vec<usize>);
|
|||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct DebugLocationValue(pub DebugScopeValue, pub usize);
|
pub struct DebugLocationValue(pub DebugScopeValue, pub usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct DebugTypeValue(pub usize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub struct DebugMetadataValue(pub usize);
|
pub struct DebugMetadataValue(pub usize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct DebugSubprogramValue(pub usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugFileData {
|
pub struct DebugFileData {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -20,17 +26,29 @@ pub struct DebugFileData {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct DebugScopeHolder {
|
pub(crate) struct DebugScopeHolder {
|
||||||
value: DebugScopeValue,
|
pub(crate) value: DebugScopeValue,
|
||||||
location: Option<DebugLocation>,
|
pub(crate) location: Option<DebugLocation>,
|
||||||
inner_scopes: Vec<DebugScopeHolder>,
|
pub(crate) inner_scopes: Vec<DebugScopeHolder>,
|
||||||
locations: Vec<DebugLocationHolder>,
|
pub(crate) locations: Vec<DebugLocationHolder>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugMetadataHolder {
|
pub struct DebugMetadataHolder {
|
||||||
scope: DebugScopeValue,
|
pub(crate) scope: DebugScopeValue,
|
||||||
value: DebugMetadataValue,
|
pub(crate) value: DebugMetadataValue,
|
||||||
data: DebugMetadata,
|
pub(crate) data: DebugMetadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugTypeHolder {
|
||||||
|
pub(crate) value: DebugTypeValue,
|
||||||
|
pub(crate) data: DebugTypeData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugSubprogramHolder {
|
||||||
|
pub(crate) value: DebugSubprogramValue,
|
||||||
|
pub(crate) data: DebugSubprogramData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -39,17 +57,13 @@ pub(crate) struct DebugLocationHolder {
|
|||||||
location: DebugLocation,
|
location: DebugLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DebugLocation {
|
|
||||||
pub line: u32,
|
|
||||||
pub column: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugInformation {
|
pub struct DebugInformation {
|
||||||
file: DebugFileData,
|
pub file: DebugFileData,
|
||||||
scope: Rc<RefCell<DebugScopeHolder>>,
|
scope: Rc<RefCell<DebugScopeHolder>>,
|
||||||
|
subprograms: Rc<RefCell<Vec<DebugSubprogramHolder>>>,
|
||||||
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
|
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
|
||||||
|
types: Rc<RefCell<Vec<DebugTypeHolder>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugInformation {
|
impl DebugInformation {
|
||||||
@ -65,6 +79,8 @@ impl DebugInformation {
|
|||||||
location: None,
|
location: None,
|
||||||
})),
|
})),
|
||||||
metadata: Rc::new(RefCell::new(Vec::new())),
|
metadata: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
subprograms: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
types: Rc::new(RefCell::new(Vec::new())),
|
||||||
},
|
},
|
||||||
scope_value,
|
scope_value,
|
||||||
)
|
)
|
||||||
@ -120,6 +136,16 @@ impl DebugInformation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn debug_type(&self, kind: DebugTypeData) -> DebugTypeValue {
|
||||||
|
let mut types = self.types.borrow_mut();
|
||||||
|
let value = DebugTypeValue(types.len());
|
||||||
|
types.push(DebugTypeHolder {
|
||||||
|
value: value.clone(),
|
||||||
|
data: kind,
|
||||||
|
});
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
pub fn metadata(&self, scope: &DebugScopeValue, kind: DebugMetadata) -> DebugMetadataValue {
|
pub fn metadata(&self, scope: &DebugScopeValue, kind: DebugMetadata) -> DebugMetadataValue {
|
||||||
let mut metadata = self.metadata.borrow_mut();
|
let mut metadata = self.metadata.borrow_mut();
|
||||||
let value = DebugMetadataValue(metadata.len());
|
let value = DebugMetadataValue(metadata.len());
|
||||||
@ -130,25 +156,133 @@ impl DebugInformation {
|
|||||||
});
|
});
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_metadata(&self, scope: &DebugScopeValue, metadata: &DebugMetadata) {
|
||||||
|
match &metadata {
|
||||||
|
DebugMetadata::ParamVar(debug_param_variable) => todo!(),
|
||||||
|
DebugMetadata::LocalVar(debug_local_variable) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subprogram(&self, kind: DebugSubprogramData) -> DebugSubprogramValue {
|
||||||
|
let mut subprogram = self.subprograms.borrow_mut();
|
||||||
|
let value = DebugSubprogramValue(subprogram.len());
|
||||||
|
subprogram.push(DebugSubprogramHolder {
|
||||||
|
value: value.clone(),
|
||||||
|
data: kind,
|
||||||
|
});
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_metadata(&self) -> Rc<RefCell<Vec<DebugMetadataHolder>>> {
|
||||||
|
self.metadata.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_scopes(&self) -> Rc<RefCell<DebugScopeHolder>> {
|
||||||
|
self.scope.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_subprograms(&self) -> Rc<RefCell<Vec<DebugSubprogramHolder>>> {
|
||||||
|
self.subprograms.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_types(&self) -> Rc<RefCell<Vec<DebugTypeHolder>>> {
|
||||||
|
self.types.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_subprogram_data(&self, value: &DebugSubprogramValue) -> DebugSubprogramData {
|
||||||
|
unsafe {
|
||||||
|
self.subprograms
|
||||||
|
.borrow()
|
||||||
|
.get_unchecked(value.0)
|
||||||
|
.data
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct DebugLocation {
|
||||||
|
pub line: u32,
|
||||||
|
pub column: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DebugMetadata {
|
pub enum DebugMetadata {
|
||||||
Function(DebugFunction),
|
|
||||||
BasicType(DebugBasicType),
|
|
||||||
ParamVar(DebugParamVariable),
|
ParamVar(DebugParamVariable),
|
||||||
LocalVar(DebugLocalVariable),
|
LocalVar(DebugLocalVariable),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugBasicType {
|
pub struct DebugParamVariable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub size_bits: u32,
|
/// the index (starting from 1) of this variable in the subprogram
|
||||||
pub encoding: AteEncoding,
|
/// parameters. arg_idx should not conflict with other parameters of the
|
||||||
|
/// same subprogram.
|
||||||
|
pub arg_idx: u32,
|
||||||
|
/// Used for line number
|
||||||
|
pub location: DebugLocation,
|
||||||
|
pub ty: DebugTypeValue,
|
||||||
|
/// If this variable will be referenced from its containing subprogram, and
|
||||||
|
/// will survive some optimizations.
|
||||||
|
pub always_preserve: bool,
|
||||||
|
pub flags: DwarfFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AteEncoding {
|
pub struct DebugLocalVariable {
|
||||||
|
pub name: String,
|
||||||
|
pub location: DebugLocation,
|
||||||
|
pub ty: DebugMetadataValue,
|
||||||
|
pub always_preserve: bool,
|
||||||
|
pub alignment: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DebugSubprogramOptionals {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
scope_line: 0,
|
||||||
|
is_local: false,
|
||||||
|
is_definition: true,
|
||||||
|
is_optimized: false,
|
||||||
|
flags: DwarfFlags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DwarfFlags;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DebugTypeData {
|
||||||
|
Basic(DebugBasicType),
|
||||||
|
Subprogram(DebugSubprogramTypeData),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugBasicType {
|
||||||
|
pub name: String,
|
||||||
|
/// Size of the type.
|
||||||
|
pub size_bits: u64,
|
||||||
|
/// DWARF encoding code, e.g., dwarf::DW_ATE_float.
|
||||||
|
pub encoding: DwarfEncoding,
|
||||||
|
/// Optional DWARF attributes, e.g., DW_AT_endianity.
|
||||||
|
pub flags: DwarfFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugSubprogramTypeData {
|
||||||
|
pub parameters: Vec<DebugTypeValue>,
|
||||||
|
pub flags: DwarfFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DebugSubprogramType {
|
||||||
|
pub params: Vec<DebugSubprogramValue>,
|
||||||
|
pub flags: DwarfFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum DwarfEncoding {
|
||||||
Address = 1,
|
Address = 1,
|
||||||
Boolean = 2,
|
Boolean = 2,
|
||||||
Float = 4,
|
Float = 4,
|
||||||
@ -159,34 +293,25 @@ pub enum AteEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugFunction {
|
pub struct DebugSubprogramData {
|
||||||
pub scope: DebugScopeValue,
|
/// Function name.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub linkage_name: String,
|
pub scope: DebugScopeValue,
|
||||||
|
/// Used for line number.
|
||||||
pub location: DebugLocation,
|
pub location: DebugLocation,
|
||||||
pub return_ty: DebugMetadataValue,
|
/// Function type.
|
||||||
|
pub ty: DebugTypeValue,
|
||||||
|
pub opts: DebugSubprogramOptionals,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugSubprogramOptionals {
|
||||||
|
/// Set to the beginning of the scope this starts
|
||||||
|
pub scope_line: u32,
|
||||||
pub is_local: bool,
|
pub is_local: bool,
|
||||||
pub is_definition: bool,
|
pub is_definition: bool,
|
||||||
pub is_optimized: bool,
|
pub is_optimized: bool,
|
||||||
pub scope_line: u32,
|
/// These flags are used to emit dwarf attributes. e.g. is this function
|
||||||
}
|
/// prototyped or not.
|
||||||
|
pub flags: DwarfFlags,
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DebugParamVariable {
|
|
||||||
pub scope: DebugScopeValue,
|
|
||||||
pub name: String,
|
|
||||||
pub arg_idx: u32,
|
|
||||||
pub location: DebugLocation,
|
|
||||||
pub ty: DebugMetadataValue,
|
|
||||||
pub always_preserve: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DebugLocalVariable {
|
|
||||||
pub scope: DebugScopeValue,
|
|
||||||
pub name: String,
|
|
||||||
pub location: DebugLocation,
|
|
||||||
pub ty: DebugMetadataValue,
|
|
||||||
pub always_preserve: bool,
|
|
||||||
pub alignment: u32,
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue,
|
|||||||
use debug::PrintableModule;
|
use debug::PrintableModule;
|
||||||
use debug_information::{
|
use debug_information::{
|
||||||
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
||||||
DebugScopeValue,
|
DebugScopeValue, DebugSubprogramValue,
|
||||||
};
|
};
|
||||||
use util::match_types;
|
use util::match_types;
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ pub struct Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new() -> Context {
|
pub fn new<T: Into<String>>(producer: T) -> Context {
|
||||||
Context {
|
Context {
|
||||||
builder: Builder::new(),
|
builder: Builder::new(producer.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ impl<'ctx> Module<'ctx> {
|
|||||||
ret,
|
ret,
|
||||||
params,
|
params,
|
||||||
flags,
|
flags,
|
||||||
meta: None,
|
debug: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ pub struct FunctionData {
|
|||||||
ret: Type,
|
ret: Type,
|
||||||
params: Vec<Type>,
|
params: Vec<Type>,
|
||||||
flags: FunctionFlags,
|
flags: FunctionFlags,
|
||||||
meta: Option<DebugMetadataValue>,
|
debug: Option<DebugSubprogramValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash)]
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
@ -177,9 +177,9 @@ impl<'ctx> Function<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_metadata(&self, metadata: DebugMetadataValue) {
|
pub fn set_debug(&self, subprogram: DebugSubprogramValue) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.builder.add_function_metadata(&self.value, metadata);
|
self.builder.set_debug_subprogram(&self.value, subprogram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ fn main() {
|
|||||||
};
|
};
|
||||||
println!("test1");
|
println!("test1");
|
||||||
|
|
||||||
let context = Context::new();
|
let context = Context::new("testcodegen");
|
||||||
let codegen = mir_context.codegen(&context);
|
let codegen = mir_context.codegen(&context);
|
||||||
println!("test2");
|
println!("test2");
|
||||||
|
|
||||||
|
@ -4,15 +4,22 @@ use reid_lib::{
|
|||||||
builder::{InstructionValue, TypeValue},
|
builder::{InstructionValue, TypeValue},
|
||||||
compile::CompiledModule,
|
compile::CompiledModule,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
AteEncoding, DebugBasicType, DebugFileData, DebugFunction, DebugInformation, DebugLocation,
|
DebugBasicType, DebugFileData, DebugInformation, DebugLocation, DebugMetadata,
|
||||||
DebugMetadata, DebugMetadataValue, DebugScopeValue,
|
DebugMetadataValue, DebugParamVariable, DebugScopeValue, DebugSubprogramData,
|
||||||
|
DebugSubprogramOptionals, DebugSubprogramTypeData, DebugSubprogramValue, DebugTypeData,
|
||||||
|
DebugTypeValue, DwarfEncoding, DwarfFlags,
|
||||||
},
|
},
|
||||||
Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
|
Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
|
||||||
Module, NamedStruct, TerminatorKind as Term, Type,
|
Module, NamedStruct, TerminatorKind as Term, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::mir::{
|
use crate::{
|
||||||
self, NamedVariableRef, StructField, StructType, TypeDefinitionKind, TypeKind, VagueLiteral,
|
error_raporting::ModuleMap,
|
||||||
|
lexer::{FullToken, Position},
|
||||||
|
mir::{
|
||||||
|
self, Metadata, NamedVariableRef, StructField, StructType, TypeDefinitionKind, TypeKind,
|
||||||
|
VagueLiteral,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Context that contains all of the given modules as complete codegenerated
|
/// Context that contains all of the given modules as complete codegenerated
|
||||||
@ -32,10 +39,24 @@ impl<'ctx> CodegenContext<'ctx> {
|
|||||||
|
|
||||||
impl mir::Context {
|
impl mir::Context {
|
||||||
/// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR.
|
/// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR.
|
||||||
pub fn codegen<'ctx>(&self, context: &'ctx Context) -> CodegenContext<'ctx> {
|
pub fn codegen<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &'ctx Context,
|
||||||
|
mod_map: &ModuleMap,
|
||||||
|
) -> CodegenContext<'ctx> {
|
||||||
let mut modules = Vec::new();
|
let mut modules = Vec::new();
|
||||||
for module in &self.modules {
|
for module in &self.modules {
|
||||||
modules.push(module.codegen(context));
|
modules.push(
|
||||||
|
module.codegen(
|
||||||
|
context,
|
||||||
|
mod_map
|
||||||
|
.module(&module.module_id)
|
||||||
|
.unwrap()
|
||||||
|
.tokens
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
CodegenContext { context }
|
CodegenContext { context }
|
||||||
}
|
}
|
||||||
@ -53,16 +74,22 @@ impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> {
|
|||||||
|
|
||||||
pub struct Scope<'ctx, 'a> {
|
pub struct Scope<'ctx, 'a> {
|
||||||
context: &'ctx Context,
|
context: &'ctx Context,
|
||||||
|
tokens: &'ctx Vec<FullToken>,
|
||||||
module: &'ctx Module<'ctx>,
|
module: &'ctx Module<'ctx>,
|
||||||
function: &'ctx Function<'ctx>,
|
function: &'ctx StackFunction<'ctx>,
|
||||||
block: Block<'ctx>,
|
block: Block<'ctx>,
|
||||||
types: &'a HashMap<TypeValue, TypeDefinitionKind>,
|
types: &'a HashMap<TypeValue, TypeDefinitionKind>,
|
||||||
type_values: &'a HashMap<String, TypeValue>,
|
type_values: &'a HashMap<String, TypeValue>,
|
||||||
functions: &'a HashMap<String, Function<'ctx>>,
|
functions: &'a HashMap<String, StackFunction<'ctx>>,
|
||||||
stack_values: HashMap<String, StackValue>,
|
stack_values: HashMap<String, StackValue>,
|
||||||
debug: &'ctx DebugInformation,
|
debug: &'ctx DebugInformation,
|
||||||
debug_scope: DebugScopeValue,
|
debug_scope: DebugScopeValue,
|
||||||
debug_const_tys: &'a HashMap<TypeKind, DebugMetadataValue>,
|
debug_const_tys: &'a HashMap<TypeKind, DebugTypeValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StackFunction<'ctx> {
|
||||||
|
ir: Function<'ctx>,
|
||||||
|
debug: DebugSubprogramValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -79,6 +106,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> {
|
fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> {
|
||||||
Scope {
|
Scope {
|
||||||
block,
|
block,
|
||||||
|
tokens: self.tokens,
|
||||||
function: self.function,
|
function: self.function,
|
||||||
context: self.context,
|
context: self.context,
|
||||||
module: self.module,
|
module: self.module,
|
||||||
@ -126,7 +154,11 @@ impl Default for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Module {
|
impl mir::Module {
|
||||||
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
|
fn codegen<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &'ctx Context,
|
||||||
|
tokens: &Vec<FullToken>,
|
||||||
|
) -> ModuleCodegen<'ctx> {
|
||||||
let mut module = context.module(&self.name, self.is_main);
|
let mut module = context.module(&self.name, self.is_main);
|
||||||
|
|
||||||
let (debug, debug_scope) = if let Some(path) = &self.path {
|
let (debug, debug_scope) = if let Some(path) = &self.path {
|
||||||
@ -147,14 +179,12 @@ impl mir::Module {
|
|||||||
|
|
||||||
debug_const_types.insert(
|
debug_const_types.insert(
|
||||||
TypeKind::U32,
|
TypeKind::U32,
|
||||||
debug.metadata(
|
debug.debug_type(DebugTypeData::Basic(DebugBasicType {
|
||||||
&debug_scope,
|
name: String::from("u32"),
|
||||||
DebugMetadata::BasicType(DebugBasicType {
|
size_bits: 32,
|
||||||
name: String::from("u32"),
|
encoding: DwarfEncoding::Unsigned,
|
||||||
size_bits: 32,
|
flags: DwarfFlags,
|
||||||
encoding: AteEncoding::Unsigned,
|
})),
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
for typedef in &self.typedefs {
|
for typedef in &self.typedefs {
|
||||||
@ -209,15 +239,69 @@ impl mir::Module {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
functions.insert(function.name.clone(), func);
|
|
||||||
|
let fn_return_ty = debug_const_types.get(&TypeKind::U32).unwrap();
|
||||||
|
|
||||||
|
let debug_ty = debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramTypeData {
|
||||||
|
parameters: vec![*fn_return_ty],
|
||||||
|
flags: DwarfFlags,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let subprogram = debug.subprogram(DebugSubprogramData {
|
||||||
|
name: function.name.clone(),
|
||||||
|
scope: debug_scope.clone(),
|
||||||
|
location: DebugLocation { line: 0, column: 0 },
|
||||||
|
ty: debug_ty,
|
||||||
|
opts: DebugSubprogramOptionals {
|
||||||
|
is_local: !function.is_pub,
|
||||||
|
is_definition: true,
|
||||||
|
..DebugSubprogramOptionals::default()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
func.set_debug(subprogram);
|
||||||
|
|
||||||
|
functions.insert(
|
||||||
|
function.name.clone(),
|
||||||
|
StackFunction {
|
||||||
|
ir: func,
|
||||||
|
debug: subprogram,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for mir_function in &self.functions {
|
for mir_function in &self.functions {
|
||||||
let function = functions.get(&mir_function.name).unwrap();
|
let function = functions.get(&mir_function.name).unwrap();
|
||||||
let mut entry = function.block("entry");
|
let mut entry = function.ir.block("entry");
|
||||||
|
|
||||||
|
let location = match &mir_function.kind {
|
||||||
|
mir::FunctionDefinitionKind::Local(_, metadata) => {
|
||||||
|
metadata.into_debug(tokens).unwrap()
|
||||||
|
}
|
||||||
|
mir::FunctionDefinitionKind::Extern(_) => {
|
||||||
|
// TODO extern should probably still have a meta
|
||||||
|
DebugLocation {
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let debug_scope = debug.inner_scope(&debug_scope, location);
|
||||||
|
|
||||||
let mut stack_values = HashMap::new();
|
let mut stack_values = HashMap::new();
|
||||||
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
|
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
|
||||||
|
debug.metadata(
|
||||||
|
&debug_scope,
|
||||||
|
DebugMetadata::ParamVar(DebugParamVariable {
|
||||||
|
name: p_name.clone(),
|
||||||
|
arg_idx: i as u32,
|
||||||
|
location,
|
||||||
|
ty: *debug_const_types.get(&TypeKind::U32).unwrap(),
|
||||||
|
always_preserve: true,
|
||||||
|
flags: DwarfFlags,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
stack_values.insert(
|
stack_values.insert(
|
||||||
p_name.clone(),
|
p_name.clone(),
|
||||||
StackValue(
|
StackValue(
|
||||||
@ -229,6 +313,7 @@ impl mir::Module {
|
|||||||
|
|
||||||
let mut scope = Scope {
|
let mut scope = Scope {
|
||||||
context,
|
context,
|
||||||
|
tokens,
|
||||||
module: &module,
|
module: &module,
|
||||||
function,
|
function,
|
||||||
block: entry,
|
block: entry,
|
||||||
@ -237,9 +322,10 @@ impl mir::Module {
|
|||||||
type_values: &type_values,
|
type_values: &type_values,
|
||||||
stack_values,
|
stack_values,
|
||||||
debug: &debug,
|
debug: &debug,
|
||||||
debug_scope: debug_scope.clone(),
|
debug_scope: debug_scope,
|
||||||
debug_const_tys: &debug_const_types,
|
debug_const_tys: &debug_const_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
match &mir_function.kind {
|
match &mir_function.kind {
|
||||||
mir::FunctionDefinitionKind::Local(block, _) => {
|
mir::FunctionDefinitionKind::Local(block, _) => {
|
||||||
let state = State::default();
|
let state = State::default();
|
||||||
@ -252,23 +338,6 @@ impl mir::Module {
|
|||||||
scope.block.terminate(Term::RetVoid).ok();
|
scope.block.terminate(Term::RetVoid).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_return_ty = debug_const_types.get(&TypeKind::U32).unwrap();
|
|
||||||
|
|
||||||
scope.function.set_metadata(scope.debug.metadata(
|
|
||||||
&scope.debug_scope,
|
|
||||||
DebugMetadata::Function(DebugFunction {
|
|
||||||
scope: scope.debug_scope.clone(),
|
|
||||||
name: mir_function.name.clone(),
|
|
||||||
linkage_name: String::new(),
|
|
||||||
location: DebugLocation { line: 0, column: 0 },
|
|
||||||
return_ty: fn_return_ty.clone(),
|
|
||||||
is_local: true,
|
|
||||||
is_definition: true,
|
|
||||||
is_optimized: false,
|
|
||||||
scope_line: 0,
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
mir::FunctionDefinitionKind::Extern(_) => {}
|
mir::FunctionDefinitionKind::Extern(_) => {}
|
||||||
}
|
}
|
||||||
@ -444,13 +513,13 @@ impl mir::Expression {
|
|||||||
Some(
|
Some(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::FunctionCall(callee.value(), params))
|
.build(Instr::FunctionCall(callee.ir.value(), params))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state),
|
mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state),
|
||||||
mir::ExprKind::Block(block) => {
|
mir::ExprKind::Block(block) => {
|
||||||
let mut inner_scope = scope.with_block(scope.function.block("inner"));
|
let mut inner_scope = scope.with_block(scope.function.ir.block("inner"));
|
||||||
if let Some(ret) = block.codegen(&mut inner_scope, state) {
|
if let Some(ret) = block.codegen(&mut inner_scope, state) {
|
||||||
inner_scope
|
inner_scope
|
||||||
.block
|
.block
|
||||||
@ -587,9 +656,9 @@ impl mir::IfExpression {
|
|||||||
let condition = self.0.codegen(scope, state).unwrap();
|
let condition = self.0.codegen(scope, state).unwrap();
|
||||||
|
|
||||||
// Create blocks
|
// Create blocks
|
||||||
let then_b = scope.function.block("then");
|
let then_b = scope.function.ir.block("then");
|
||||||
let mut else_b = scope.function.block("else");
|
let mut else_b = scope.function.ir.block("else");
|
||||||
let after_b = scope.function.block("after");
|
let after_b = scope.function.ir.block("after");
|
||||||
|
|
||||||
// Store for convenience
|
// Store for convenience
|
||||||
let then_bb = then_b.value();
|
let then_bb = then_b.value();
|
||||||
@ -709,3 +778,22 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Metadata {
|
||||||
|
pub fn into_debug(&self, tokens: &Vec<FullToken>) -> Option<DebugLocation> {
|
||||||
|
if let Some((start, _)) = self.into_positions(tokens) {
|
||||||
|
Some(start.into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<DebugLocation> for Position {
|
||||||
|
fn into(self) -> DebugLocation {
|
||||||
|
DebugLocation {
|
||||||
|
line: self.1,
|
||||||
|
column: self.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -69,7 +69,7 @@ impl Ord for ErrorKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ErrModule {
|
pub struct Module {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub tokens: Option<Vec<FullToken>>,
|
pub tokens: Option<Vec<FullToken>>,
|
||||||
pub source: Option<String>,
|
pub source: Option<String>,
|
||||||
@ -77,7 +77,7 @@ pub struct ErrModule {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
pub struct ModuleMap {
|
pub struct ModuleMap {
|
||||||
module_map: HashMap<mir::SourceModuleId, ErrModule>,
|
module_map: HashMap<mir::SourceModuleId, Module>,
|
||||||
module_counter: mir::SourceModuleId,
|
module_counter: mir::SourceModuleId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ impl ModuleMap {
|
|||||||
let id = self.module_counter.increment();
|
let id = self.module_counter.increment();
|
||||||
self.module_map.insert(
|
self.module_map.insert(
|
||||||
id,
|
id,
|
||||||
ErrModule {
|
Module {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
source: None,
|
source: None,
|
||||||
@ -107,7 +107,7 @@ impl ModuleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_module(&self, id: &mir::SourceModuleId) -> Option<&ErrModule> {
|
pub fn module(&self, id: &mir::SourceModuleId) -> Option<&Module> {
|
||||||
self.module_map.get(id)
|
self.module_map.get(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ impl std::fmt::Display for ReidError {
|
|||||||
let mut curr_module = None;
|
let mut curr_module = None;
|
||||||
for error in sorted_errors {
|
for error in sorted_errors {
|
||||||
let meta = error.get_meta();
|
let meta = error.get_meta();
|
||||||
let module = self.map.get_module(&meta.source_module_id).unwrap();
|
let module = self.map.module(&meta.source_module_id).unwrap();
|
||||||
let position = if let Some(tokens) = &module.tokens {
|
let position = if let Some(tokens) = &module.tokens {
|
||||||
let range_tokens = meta.range.into_tokens(&tokens);
|
let range_tokens = meta.range.into_tokens(&tokens);
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ pub fn compile_module<'map>(
|
|||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
is_main: bool,
|
is_main: bool,
|
||||||
) -> Result<mir::Module, ReidError> {
|
) -> Result<mir::Module, ReidError> {
|
||||||
let module = map.get_module(&module_id).cloned().unwrap();
|
let module = map.module(&module_id).cloned().unwrap();
|
||||||
|
|
||||||
let mut token_stream = TokenStream::from(&tokens);
|
let mut token_stream = TokenStream::from(&tokens);
|
||||||
|
|
||||||
@ -196,8 +196,8 @@ pub fn compile_and_pass<'map>(
|
|||||||
|
|
||||||
perform_all_passes(&mut mir_context, module_map)?;
|
perform_all_passes(&mut mir_context, module_map)?;
|
||||||
|
|
||||||
let mut context = Context::new();
|
let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION")));
|
||||||
let codegen_modules = mir_context.codegen(&mut context);
|
let codegen_modules = mir_context.codegen(&mut context, &module_map);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&codegen_modules);
|
dbg!(&codegen_modules);
|
||||||
|
@ -87,7 +87,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
for module in context.modules.drain(..) {
|
for module in context.modules.drain(..) {
|
||||||
let tokens = self
|
let tokens = self
|
||||||
.module_map
|
.module_map
|
||||||
.get_module(&module.module_id)
|
.module(&module.module_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.tokens
|
.tokens
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::{lexer::Position, token_stream::TokenRange};
|
use crate::{
|
||||||
|
lexer::{FullToken, Position},
|
||||||
|
token_stream::TokenRange,
|
||||||
|
};
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
pub mod r#impl;
|
pub mod r#impl;
|
||||||
@ -36,6 +39,19 @@ impl Metadata {
|
|||||||
(self.range.start >= other.range.start && self.range.end <= other.range.end)
|
(self.range.start >= other.range.start && self.range.end <= other.range.end)
|
||||||
|| (other.range.start >= self.range.start && other.range.end <= self.range.end)
|
|| (other.range.start >= self.range.start && other.range.end <= self.range.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_positions(&self, tokens: &Vec<FullToken>) -> Option<(Position, Position)> {
|
||||||
|
let mut iter = tokens
|
||||||
|
.iter()
|
||||||
|
.skip(self.range.start)
|
||||||
|
.take(self.range.end - self.range.start);
|
||||||
|
if let Some(first) = iter.next() {
|
||||||
|
let last = iter.last().unwrap();
|
||||||
|
Some((first.position, last.position.add(last.token.len() as u32)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Add for Metadata {
|
impl std::ops::Add for Metadata {
|
||||||
@ -248,7 +264,9 @@ pub struct FunctionCall {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FunctionDefinition {
|
pub struct FunctionDefinition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// Whether this function is visible to outside modules
|
||||||
pub is_pub: bool,
|
pub is_pub: bool,
|
||||||
|
/// Whether this module is from an external module, and has been imported
|
||||||
pub is_imported: bool,
|
pub is_imported: bool,
|
||||||
pub return_type: TypeKind,
|
pub return_type: TypeKind,
|
||||||
pub parameters: Vec<(String, TypeKind)>,
|
pub parameters: Vec<(String, TypeKind)>,
|
||||||
|
Loading…
Reference in New Issue
Block a user