Compare commits
No commits in common. "e1d014bcc2c363141bcd59f4ce7c754de4c59082" and "9bb4f97e6b732afdeedb8e35e7a56966dfb52ce2" have entirely different histories.
e1d014bcc2
...
9bb4f97e6b
52
Cargo.lock
generated
52
Cargo.lock
generated
@ -3,10 +3,13 @@
|
|||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "aho-corasick"
|
||||||
version = "1.0.98"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
@ -40,18 +43,23 @@ checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "llvm-sys"
|
name = "llvm-sys"
|
||||||
version = "201.0.1"
|
version = "160.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9bb947e8b79254ca10d496d0798a9ba1287dcf68e50a92b016fec1cc45bef447"
|
checksum = "e73861901245d32e1c3d8b35b639cf100859b4cd0c9da56fe0273040acbb3ea4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"cc",
|
"cc",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"regex-lite",
|
"regex",
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.95"
|
version = "1.0.95"
|
||||||
@ -71,16 +79,40 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-lite"
|
name = "regex"
|
||||||
version = "0.1.6"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reid"
|
name = "reid"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored",
|
"colored",
|
||||||
|
"llvm-sys",
|
||||||
"reid-lib",
|
"reid-lib",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
50
README.md
50
README.md
@ -77,42 +77,42 @@ change erratically.
|
|||||||
This is what worked for me, might not (probably) work for you, depending on
|
This is what worked for me, might not (probably) work for you, depending on
|
||||||
various versions of various libraries.
|
various versions of various libraries.
|
||||||
|
|
||||||
### Compiling LLVM 20.1.8
|
### Compiling LLVM 16.0.0
|
||||||
|
|
||||||
#### Context
|
#### Context
|
||||||
Context for my computer. I am on ArchLinux, and here are some libraries and
|
Context for my computer. I am on ArchLinux, and here are some libraries and
|
||||||
their current versions that I have installed as of compiling, I'm not sure what
|
their current versions that I have installed as of compiling, I'm not sure what
|
||||||
of them are relevant, if any, but saving them here still feels like a good idea
|
of them are relevant, if any, but saving them here still feels like a good idea
|
||||||
for the future:
|
for the future:
|
||||||
- `clang 19.1.7-2`
|
- `cmake 3.27.0-1`
|
||||||
- `cmake 4.0.2-1`
|
- `lib32-llvm-libs 15.0.7-1`
|
||||||
- `extra-cmake-modules 6.14.0-1`
|
- `llvm 15.0.7-3`
|
||||||
- `gcc 15.1.1+r7+gf36ec88aa85a-1`
|
- `llvm-libs 15.0.7-3`
|
||||||
- `gcc-libs 15.1.1+r7+gf36ec88aa85a-1`
|
- `gcc 13.1.1-2`
|
||||||
- `lib32-gcc-libs 15.1.1+r7+gf36ec88aa85a-1`
|
- `gcc-libs 13.1.1-2`
|
||||||
- `lib32-llvm-libs 1:19.1.7-2`
|
- `lib32-gcc-libs 13.1.1-2`
|
||||||
- `libgccjit 15.1.1+r7+gf36ec88aa85a-1`
|
- `lld 15.0.7-2`
|
||||||
- `lld 19.1.7-1`
|
- `lldb 15.0.7-3`
|
||||||
- `lldb 19.1.7-2`
|
- `clang 15.0.7-9`
|
||||||
- `llvm 19.1.7-2`
|
|
||||||
- `llvm-libs 19.1.7-2`
|
|
||||||
- `llvm14 14.0.6-5`
|
|
||||||
- `llvm14-libs 14.0.6-5`
|
|
||||||
- `llvm15 15.0.7-3`
|
|
||||||
- `llvm15-libs 15.0.7-3`
|
|
||||||
- `make 4.4.1-2`
|
- `make 4.4.1-2`
|
||||||
|
- `automake 1.16.5-2`
|
||||||
|
|
||||||
#### Commands
|
#### Commands
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/llvm/llvm-project.git --depth=1 --branch=llvmorg-20.1.8
|
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.0/llvm-16.0.0.src.tar.xz
|
||||||
|
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.0/cmake-16.0.0.src.tar.xz
|
||||||
|
|
||||||
cd llvm_project
|
tar xvf llvm-16.0.0.src.tar.xz
|
||||||
|
tar xvf cmake-16.0.0.src.tar.xz
|
||||||
|
|
||||||
cmake llvm -B build -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INCLUDE_TESTS=OFF -DLLVM_BUILD_BENCHMARKS=OFF -G Ninja -DLLVM_USE_LINKER="ld.lld" -DLLVM_PARALLEL_LINK_JOBS=8
|
mv cmake-16.0.0.src cmake
|
||||||
|
|
||||||
ninja -j23
|
cd llvm-16.0.0.src
|
||||||
|
|
||||||
|
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/llvm-16 -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INCLUDE_TESTS=OFF
|
||||||
|
|
||||||
|
make -j8
|
||||||
```
|
```
|
||||||
|
|
||||||
*Also Note:* Building LLVM with `Ninja` was not successful for me, but this
|
*Also Note:* Building LLVM with `Ninja` was not successful for me, but this
|
||||||
@ -121,11 +121,11 @@ method was. Ninja may be successful with you, to try it, add `-G Ninja` to the
|
|||||||
|
|
||||||
### Building this crate itself
|
### Building this crate itself
|
||||||
|
|
||||||
Assuming `llvm-project` from the previous step was at
|
Assuming `llvm-16.0.0.src` from the previous step was at
|
||||||
`/path/llvm-project`, building this crate can be done via the following command:
|
`/path/llvm-16.0.0.src`, building this crate can be done via the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
LLVM_SYS_201_PREFIX=/path/llvm-project/build cargo build
|
LLVM_SYS_160_PREFIX=/path/llvm-16.0.0.src/build cargo build
|
||||||
```
|
```
|
||||||
|
|
||||||
## In conclusion
|
## In conclusion
|
||||||
|
@ -7,6 +7,6 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
## LLVM Bindings
|
## LLVM Bindings
|
||||||
llvm-sys = {version ="201.0.1", features=["force-static"] }
|
llvm-sys = "160"
|
||||||
## Make it easier to generate errors
|
## Make it easier to generate errors
|
||||||
thiserror = "1.0.44"
|
thiserror = "1.0.44"
|
@ -4,9 +4,9 @@ fn main() {
|
|||||||
use ConstValue::*;
|
use ConstValue::*;
|
||||||
use Instr::*;
|
use Instr::*;
|
||||||
|
|
||||||
let context = Context::new("libtest");
|
let context = Context::new();
|
||||||
|
|
||||||
let module = context.module("test", true);
|
let mut 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");
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct,
|
BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct,
|
||||||
TerminatorKind, Type, TypeData,
|
TerminatorKind, Type, TypeData,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue,
|
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
||||||
},
|
},
|
||||||
util::match_types,
|
util::match_types,
|
||||||
};
|
};
|
||||||
@ -65,14 +65,12 @@ 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(producer: String) -> Builder {
|
pub fn new() -> Builder {
|
||||||
Builder {
|
Builder {
|
||||||
modules: Rc::new(RefCell::new(Vec::new())),
|
modules: Rc::new(RefCell::new(Vec::new())),
|
||||||
producer,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,16 +193,16 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn set_debug_subprogram(
|
pub(crate) unsafe fn add_function_metadata(
|
||||||
&self,
|
&self,
|
||||||
value: &FunctionValue,
|
value: &FunctionValue,
|
||||||
subprogram: DebugProgramValue,
|
metadata: DebugMetadataValue,
|
||||||
) {
|
) {
|
||||||
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.debug = Some(subprogram)
|
function.data.meta = Some(metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,25 +225,6 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn set_terminator_location(
|
|
||||||
&self,
|
|
||||||
block: &BlockValue,
|
|
||||||
location: DebugLocationValue,
|
|
||||||
) -> Result<(), ()> {
|
|
||||||
unsafe {
|
|
||||||
let mut modules = self.modules.borrow_mut();
|
|
||||||
let module = modules.get_unchecked_mut(block.0.0.0);
|
|
||||||
let function = module.functions.get_unchecked_mut(block.0.1);
|
|
||||||
let block = function.blocks.get_unchecked_mut(block.1);
|
|
||||||
if let Some(_) = &block.data.terminator_location {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
block.data.terminator_location = Some(location);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) unsafe fn delete_block(&self, block: &BlockValue) -> Result<(), ()> {
|
pub(crate) unsafe fn delete_block(&self, block: &BlockValue) -> Result<(), ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
use std::{collections::HashMap, ptr::null_mut};
|
use std::{collections::HashMap, ptr::null_mut};
|
||||||
|
|
||||||
use llvm_sys::{
|
use llvm_sys::{
|
||||||
LLVMIntPredicate, LLVMLinkage, LLVMValueKind,
|
LLVMIntPredicate, LLVMLinkage,
|
||||||
analysis::LLVMVerifyModule,
|
analysis::LLVMVerifyModule,
|
||||||
core::*,
|
core::*,
|
||||||
debuginfo::*,
|
|
||||||
linker::LLVMLinkModules2,
|
linker::LLVMLinkModules2,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
target::{
|
target::{
|
||||||
@ -24,7 +23,6 @@ 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},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,6 +90,14 @@ impl CompiledModule {
|
|||||||
LLVMSetTarget(self.module_ref, triple);
|
LLVMSetTarget(self.module_ref, triple);
|
||||||
LLVMSetModuleDataLayout(self.module_ref, data_layout);
|
LLVMSetModuleDataLayout(self.module_ref, data_layout);
|
||||||
|
|
||||||
|
let mut err = ErrorMessageHolder::null();
|
||||||
|
LLVMVerifyModule(
|
||||||
|
self.module_ref,
|
||||||
|
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
|
||||||
|
err.borrow_mut(),
|
||||||
|
);
|
||||||
|
err.into_result().unwrap();
|
||||||
|
|
||||||
let mut asm_buffer = MemoryBufferHolder::empty("asm");
|
let mut asm_buffer = MemoryBufferHolder::empty("asm");
|
||||||
let mut err = ErrorMessageHolder::null();
|
let mut err = ErrorMessageHolder::null();
|
||||||
LLVMTargetMachineEmitToMemoryBuffer(
|
LLVMTargetMachineEmitToMemoryBuffer(
|
||||||
@ -114,28 +120,14 @@ impl CompiledModule {
|
|||||||
);
|
);
|
||||||
err.into_result().unwrap();
|
err.into_result().unwrap();
|
||||||
|
|
||||||
let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref))
|
|
||||||
.expect("Unable to print LLVM IR to string");
|
|
||||||
|
|
||||||
let mut err = ErrorMessageHolder::null();
|
|
||||||
LLVMVerifyModule(
|
|
||||||
self.module_ref,
|
|
||||||
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
|
|
||||||
err.borrow_mut(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = err.into_result() {
|
|
||||||
println!("{}", llvm_ir);
|
|
||||||
panic!("{}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
CompileOutput {
|
CompileOutput {
|
||||||
triple: from_cstring(triple).expect("Unable to convert triple from cstring"),
|
triple: from_cstring(triple).expect("Unable to convert triple from cstring"),
|
||||||
assembly: asm_buffer
|
assembly: asm_buffer
|
||||||
.as_string()
|
.as_string()
|
||||||
.expect("Error while converting assembly-buffer to string"),
|
.expect("Error while converting assembly-buffer to string"),
|
||||||
obj_buffer: obj_buffer.as_buffer(),
|
obj_buffer: obj_buffer.as_buffer(),
|
||||||
llvm_ir,
|
llvm_ir: from_cstring(LLVMPrintModuleToString(self.module_ref))
|
||||||
|
.expect("Unable to print LLVM IR to string"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,35 +180,12 @@ 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>,
|
|
||||||
programs: &'a mut HashMap<DebugProgramValue, LLVMMetadataRef>,
|
|
||||||
metadata: &'a mut HashMap<DebugMetadataValue, LLVMMetadataRef>,
|
|
||||||
locations: &'a mut HashMap<DebugLocationValue, 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 {
|
||||||
@ -234,85 +203,6 @@ impl ModuleHolder {
|
|||||||
|
|
||||||
// Compile the contents
|
// Compile the contents
|
||||||
|
|
||||||
let mut types = HashMap::new();
|
|
||||||
let mut metadata = HashMap::new();
|
|
||||||
let mut programs = HashMap::new();
|
|
||||||
let mut locations = 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();
|
|
||||||
// scopes.insert(scope.borrow().value.clone(), compile_unit);
|
|
||||||
// for scope in &scope.borrow().inner_scopes {
|
|
||||||
// dbg!("hello");
|
|
||||||
// scope.compile_scope(compile_unit, file_ref, &mut scopes, di_builder);
|
|
||||||
// }
|
|
||||||
// dbg!("after!");
|
|
||||||
|
|
||||||
programs.insert(DebugProgramValue(0), compile_unit);
|
|
||||||
|
|
||||||
let debug = LLVMDebugInformation {
|
|
||||||
builder: di_builder,
|
|
||||||
debug: debug,
|
|
||||||
file_ref,
|
|
||||||
types: &mut types,
|
|
||||||
metadata: &mut metadata,
|
|
||||||
programs: &mut programs,
|
|
||||||
locations: &mut locations,
|
|
||||||
};
|
|
||||||
|
|
||||||
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));
|
||||||
@ -320,26 +210,10 @@ impl ModuleHolder {
|
|||||||
|
|
||||||
let mut functions = HashMap::new();
|
let mut functions = HashMap::new();
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
let func = function.compile_signature(context, module_ref, &types, &debug);
|
functions.insert(
|
||||||
functions.insert(function.value, func);
|
function.value,
|
||||||
|
function.compile_signature(context, module_ref, &types),
|
||||||
if let Some(debug) = &mut debug {
|
);
|
||||||
if let Some(program_value) = function.data.debug {
|
|
||||||
debug.programs.insert(program_value, func.metadata.unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(debug) = &mut debug {
|
|
||||||
for location in debug.debug.get_locations().borrow().iter() {
|
|
||||||
let location_ref = location.compile(context, &debug);
|
|
||||||
debug.locations.insert(location.value, location_ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
for meta in debug.debug.get_metadata().borrow().iter() {
|
|
||||||
let meta_ref = meta.compile(&debug);
|
|
||||||
debug.metadata.insert(meta.value.clone(), meta_ref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut module = LLVMModule {
|
let mut module = LLVMModule {
|
||||||
@ -351,130 +225,17 @@ 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 DebugLocationHolder {
|
|
||||||
unsafe fn compile(
|
|
||||||
&self,
|
|
||||||
context: &LLVMContext,
|
|
||||||
debug: &LLVMDebugInformation,
|
|
||||||
) -> LLVMMetadataRef {
|
|
||||||
unsafe {
|
|
||||||
LLVMDIBuilderCreateDebugLocation(
|
|
||||||
context.context_ref,
|
|
||||||
self.location.line,
|
|
||||||
self.location.column,
|
|
||||||
*debug.programs.get(&self.program).unwrap(),
|
|
||||||
null_mut(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
|
|
||||||
dbg!(&self.program);
|
|
||||||
unsafe {
|
|
||||||
match &self.data {
|
|
||||||
DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable(
|
|
||||||
debug.builder,
|
|
||||||
*debug.programs.get(&self.program).unwrap(),
|
|
||||||
into_cstring(param.name.clone()).as_ptr(),
|
|
||||||
param.name.len(),
|
|
||||||
param.arg_idx + 1,
|
|
||||||
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,
|
||||||
@ -507,7 +268,6 @@ 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);
|
||||||
@ -525,43 +285,9 @@ 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;
|
|
||||||
|
|
||||||
let subprogram = LLVMDIBuilderCreateFunction(
|
|
||||||
debug.builder,
|
|
||||||
*debug.programs.get(&subprogram.outer_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,
|
|
||||||
);
|
|
||||||
LLVMSetSubprogram(function_ref, subprogram);
|
|
||||||
Some(subprogram)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
LLVMFunction {
|
LLVMFunction {
|
||||||
type_ref: fn_type,
|
type_ref: fn_type,
|
||||||
value_ref: function_ref,
|
value_ref: function_ref,
|
||||||
metadata,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -629,8 +355,7 @@ impl BlockHolder {
|
|||||||
module.values.insert(key, ret);
|
module.values.insert(key, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
let term_instr = self
|
self.data
|
||||||
.data
|
|
||||||
.terminator
|
.terminator
|
||||||
.clone()
|
.clone()
|
||||||
.expect(&format!(
|
.expect(&format!(
|
||||||
@ -638,20 +363,6 @@ impl BlockHolder {
|
|||||||
self.data.name
|
self.data.name
|
||||||
))
|
))
|
||||||
.compile(module, function, block_ref);
|
.compile(module, function, block_ref);
|
||||||
|
|
||||||
dbg!(&self.value, &self.data.terminator_location);
|
|
||||||
if let Some(location) = &self.data.terminator_location {
|
|
||||||
LLVMInstructionSetDebugLoc(
|
|
||||||
term_instr.value_ref,
|
|
||||||
*module
|
|
||||||
.debug
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.locations
|
|
||||||
.get(&location)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -808,28 +519,6 @@ impl InstructionHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(location) = &self.data.location {
|
|
||||||
unsafe {
|
|
||||||
match LLVMGetValueKind(val) {
|
|
||||||
LLVMValueKind::LLVMInstructionValueKind
|
|
||||||
| LLVMValueKind::LLVMMemoryDefValueKind
|
|
||||||
| LLVMValueKind::LLVMMemoryUseValueKind
|
|
||||||
| LLVMValueKind::LLVMMemoryPhiValueKind => {
|
|
||||||
LLVMInstructionSetDebugLoc(
|
|
||||||
val,
|
|
||||||
*module
|
|
||||||
.debug
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.locations
|
|
||||||
.get(&location)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LLVMValue {
|
LLVMValue {
|
||||||
_ty,
|
_ty,
|
||||||
value_ref: val,
|
value_ref: val,
|
||||||
|
@ -5,10 +5,7 @@ use std::{
|
|||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*};
|
||||||
CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*,
|
|
||||||
debug_information::DebugLocationValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl Debug for Builder {
|
impl Debug for Builder {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
@ -32,7 +29,6 @@ impl Debug for ModuleHolder {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value))
|
f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value))
|
||||||
.field(&self.functions)
|
.field(&self.functions)
|
||||||
.field(&self.debug_information)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +53,6 @@ impl Debug for BlockHolder {
|
|||||||
))
|
))
|
||||||
.field(&self.instructions)
|
.field(&self.instructions)
|
||||||
.field(&self.data.terminator)
|
.field(&self.data.terminator)
|
||||||
.field(&self.data.terminator_location)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,20 +67,7 @@ impl Debug for InstructionHolder {
|
|||||||
|
|
||||||
impl Debug for InstructionData {
|
impl Debug for InstructionData {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.kind.fmt(f)?;
|
self.kind.fmt(f)
|
||||||
if let Some(location) = self.location {
|
|
||||||
write!(f, " ({:?})", location)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for DebugLocationValue {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_tuple("DebugLocationValue")
|
|
||||||
.field(&self.0)
|
|
||||||
.field(&self.1)
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct DebugScopeValue(pub Vec<usize>);
|
pub struct DebugScopeValue(pub Vec<usize>);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct DebugLocationValue(pub DebugProgramValue, pub usize);
|
pub struct DebugLocationValue(pub DebugScopeValue, pub usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, 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);
|
||||||
|
|
||||||
/// Represents either a subprogram, or the compilation context
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct DebugProgramValue(pub usize);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugFileData {
|
pub struct DebugFileData {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -24,261 +20,135 @@ pub struct DebugFileData {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct DebugScopeHolder {
|
pub(crate) struct DebugScopeHolder {
|
||||||
pub(crate) value: DebugScopeValue,
|
value: DebugScopeValue,
|
||||||
pub(crate) location: Option<DebugLocation>,
|
location: Option<DebugLocation>,
|
||||||
pub(crate) inner_scopes: Vec<DebugScopeHolder>,
|
inner_scopes: Vec<DebugScopeHolder>,
|
||||||
pub(crate) locations: Vec<DebugLocationHolder>,
|
locations: Vec<DebugLocationHolder>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugMetadataHolder {
|
pub struct DebugMetadataHolder {
|
||||||
pub(crate) program: DebugProgramValue,
|
scope: DebugScopeValue,
|
||||||
pub(crate) value: DebugMetadataValue,
|
value: DebugMetadataValue,
|
||||||
pub(crate) data: DebugMetadata,
|
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: DebugProgramValue,
|
|
||||||
pub(crate) data: DebugSubprogramData,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct DebugLocationHolder {
|
pub(crate) struct DebugLocationHolder {
|
||||||
pub(crate) program: DebugProgramValue,
|
value: DebugLocationValue,
|
||||||
pub(crate) value: DebugLocationValue,
|
location: DebugLocation,
|
||||||
pub(crate) location: DebugLocation,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugInformation {
|
|
||||||
pub file: DebugFileData,
|
|
||||||
// scope: Rc<RefCell<DebugScopeHolder>>,
|
|
||||||
locations: Rc<RefCell<Vec<DebugLocationHolder>>>,
|
|
||||||
programs: Rc<RefCell<Vec<DebugSubprogramHolder>>>,
|
|
||||||
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
|
|
||||||
types: Rc<RefCell<Vec<DebugTypeHolder>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DebugInformation {
|
|
||||||
pub fn from_file(file: DebugFileData) -> (DebugInformation, DebugProgramValue) {
|
|
||||||
(
|
|
||||||
DebugInformation {
|
|
||||||
file,
|
|
||||||
// scope: Rc::new(RefCell::new(DebugScopeHolder {
|
|
||||||
// value: scope_value.clone(),
|
|
||||||
// inner_scopes: Vec::new(),
|
|
||||||
// locations: Vec::new(),
|
|
||||||
// location: None,
|
|
||||||
// })),
|
|
||||||
locations: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
metadata: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
programs: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
types: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
},
|
|
||||||
DebugProgramValue(0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn inner_scope(
|
|
||||||
// &self,
|
|
||||||
// parent: &DebugScopeValue,
|
|
||||||
// location: DebugLocation,
|
|
||||||
// ) -> DebugScopeValue {
|
|
||||||
// unsafe {
|
|
||||||
// let mut outer_scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
|
|
||||||
// for i in &parent.0 {
|
|
||||||
// v = v.inner_scopes.get_unchecked_mut(*i);
|
|
||||||
// }
|
|
||||||
// v
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let mut arr = parent.0.clone();
|
|
||||||
// arr.push(parent.0.len());
|
|
||||||
// let value = DebugScopeValue(arr);
|
|
||||||
|
|
||||||
// outer_scope.inner_scopes.push(DebugScopeHolder {
|
|
||||||
// value: value.clone(),
|
|
||||||
// inner_scopes: Vec::new(),
|
|
||||||
// locations: Vec::new(),
|
|
||||||
// location: Some(location),
|
|
||||||
// });
|
|
||||||
// value
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn location(
|
|
||||||
&self,
|
|
||||||
program_value: &DebugProgramValue,
|
|
||||||
location: DebugLocation,
|
|
||||||
) -> DebugLocationValue {
|
|
||||||
let value = DebugLocationValue(program_value.clone(), self.locations.borrow().len());
|
|
||||||
let location = DebugLocationHolder {
|
|
||||||
program: *program_value,
|
|
||||||
value: value.clone(),
|
|
||||||
location,
|
|
||||||
};
|
|
||||||
self.locations.borrow_mut().push(location);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
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, program: &DebugProgramValue, kind: DebugMetadata) -> DebugMetadataValue {
|
|
||||||
let mut metadata = self.metadata.borrow_mut();
|
|
||||||
let value = DebugMetadataValue(metadata.len());
|
|
||||||
metadata.push(DebugMetadataHolder {
|
|
||||||
program: *program,
|
|
||||||
value: value.clone(),
|
|
||||||
data: kind,
|
|
||||||
});
|
|
||||||
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) -> DebugProgramValue {
|
|
||||||
let mut subprogram = self.programs.borrow_mut();
|
|
||||||
let value = DebugProgramValue(subprogram.len() + 1);
|
|
||||||
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.programs.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_types(&self) -> Rc<RefCell<Vec<DebugTypeHolder>>> {
|
|
||||||
self.types.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_locations(&self) -> Rc<RefCell<Vec<DebugLocationHolder>>> {
|
|
||||||
self.locations.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_subprogram_data(&self, value: &DebugProgramValue) -> DebugSubprogramData {
|
|
||||||
unsafe {
|
|
||||||
self.programs
|
|
||||||
.borrow()
|
|
||||||
.get_unchecked(value.0 - 1)
|
|
||||||
.data
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
pub struct DebugLocation {
|
pub struct DebugLocation {
|
||||||
pub line: u32,
|
pub line: u32,
|
||||||
pub column: u32,
|
pub column: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DebugInformation {
|
||||||
|
file: DebugFileData,
|
||||||
|
scope: Rc<RefCell<DebugScopeHolder>>,
|
||||||
|
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugInformation {
|
||||||
|
pub fn from_file(file: DebugFileData) -> (DebugInformation, DebugScopeValue) {
|
||||||
|
let scope_value = DebugScopeValue(Vec::new());
|
||||||
|
(
|
||||||
|
DebugInformation {
|
||||||
|
file,
|
||||||
|
scope: Rc::new(RefCell::new(DebugScopeHolder {
|
||||||
|
value: scope_value.clone(),
|
||||||
|
inner_scopes: Vec::new(),
|
||||||
|
locations: Vec::new(),
|
||||||
|
location: None,
|
||||||
|
})),
|
||||||
|
metadata: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
},
|
||||||
|
scope_value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner_scope(
|
||||||
|
&self,
|
||||||
|
parent: &DebugScopeValue,
|
||||||
|
location: DebugLocation,
|
||||||
|
) -> DebugScopeValue {
|
||||||
|
unsafe {
|
||||||
|
let mut outer_scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
|
||||||
|
for i in &parent.0 {
|
||||||
|
v = v.inner_scopes.get_unchecked_mut(*i);
|
||||||
|
}
|
||||||
|
v
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut arr = parent.0.clone();
|
||||||
|
arr.push(parent.0.len());
|
||||||
|
let value = DebugScopeValue(arr);
|
||||||
|
|
||||||
|
outer_scope.inner_scopes.push(DebugScopeHolder {
|
||||||
|
value: value.clone(),
|
||||||
|
inner_scopes: Vec::new(),
|
||||||
|
locations: Vec::new(),
|
||||||
|
location: Some(location),
|
||||||
|
});
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn location(
|
||||||
|
&self,
|
||||||
|
scope_value: &DebugScopeValue,
|
||||||
|
line: u32,
|
||||||
|
column: u32,
|
||||||
|
) -> DebugLocationValue {
|
||||||
|
unsafe {
|
||||||
|
let mut scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
|
||||||
|
for i in &scope_value.0 {
|
||||||
|
v = v.inner_scopes.get_unchecked_mut(*i);
|
||||||
|
}
|
||||||
|
v
|
||||||
|
});
|
||||||
|
let value = DebugLocationValue(scope_value.clone(), scope.locations.len());
|
||||||
|
let location = DebugLocationHolder {
|
||||||
|
value: value.clone(),
|
||||||
|
location: DebugLocation { line, column },
|
||||||
|
};
|
||||||
|
scope.locations.push(location);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn metadata(&self, scope: &DebugScopeValue, kind: DebugMetadata) -> DebugMetadataValue {
|
||||||
|
let mut metadata = self.metadata.borrow_mut();
|
||||||
|
let value = DebugMetadataValue(metadata.len());
|
||||||
|
metadata.push(DebugMetadataHolder {
|
||||||
|
scope: scope.clone(),
|
||||||
|
value: value.clone(),
|
||||||
|
data: kind,
|
||||||
|
});
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[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)]
|
|
||||||
pub struct DebugParamVariable {
|
|
||||||
pub name: String,
|
|
||||||
/// the index (starting from 1) of this variable in the subprogram
|
|
||||||
/// 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)]
|
|
||||||
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugBasicType {
|
pub struct DebugBasicType {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
/// Size of the type.
|
pub size_bits: u32,
|
||||||
pub size_bits: u64,
|
pub encoding: AteEncoding,
|
||||||
/// 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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugSubprogramTypeData {
|
pub enum AteEncoding {
|
||||||
pub parameters: Vec<DebugTypeValue>,
|
|
||||||
pub flags: DwarfFlags,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DebugSubprogramType {
|
|
||||||
pub params: Vec<DebugProgramValue>,
|
|
||||||
pub flags: DwarfFlags,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum DwarfEncoding {
|
|
||||||
Address = 1,
|
Address = 1,
|
||||||
Boolean = 2,
|
Boolean = 2,
|
||||||
Float = 4,
|
Float = 4,
|
||||||
@ -289,25 +159,34 @@ pub enum DwarfEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugSubprogramData {
|
pub struct DebugFunction {
|
||||||
/// Function name.
|
pub scope: DebugScopeValue,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub outer_scope: DebugProgramValue,
|
pub linkage_name: String,
|
||||||
/// Used for line number.
|
|
||||||
pub location: DebugLocation,
|
pub location: DebugLocation,
|
||||||
/// Function type.
|
pub return_ty: DebugMetadataValue,
|
||||||
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,
|
||||||
/// These flags are used to emit dwarf attributes. e.g. is this function
|
pub scope_line: u32,
|
||||||
/// 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,
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ use std::{fmt::Debug, marker::PhantomData};
|
|||||||
use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, TypeValue};
|
use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, TypeValue};
|
||||||
use debug::PrintableModule;
|
use debug::PrintableModule;
|
||||||
use debug_information::{
|
use debug_information::{
|
||||||
DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue,
|
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
|
||||||
|
DebugScopeValue,
|
||||||
};
|
};
|
||||||
use util::match_types;
|
use util::match_types;
|
||||||
|
|
||||||
@ -23,9 +24,9 @@ pub struct Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new<T: Into<String>>(producer: T) -> Context {
|
pub fn new() -> Context {
|
||||||
Context {
|
Context {
|
||||||
builder: Builder::new(producer.into()),
|
builder: Builder::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ impl<'ctx> Module<'ctx> {
|
|||||||
ret,
|
ret,
|
||||||
params,
|
params,
|
||||||
flags,
|
flags,
|
||||||
debug: None,
|
meta: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -105,10 +106,10 @@ impl<'ctx> Module<'ctx> {
|
|||||||
pub fn create_debug_info(
|
pub fn create_debug_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
file: DebugFileData,
|
file: DebugFileData,
|
||||||
) -> (DebugInformation, DebugProgramValue) {
|
) -> (DebugInformation, DebugScopeValue) {
|
||||||
let (debug_info, program_value) = DebugInformation::from_file(file);
|
let (debug_info, scope) = DebugInformation::from_file(file);
|
||||||
self.debug_info = Some(debug_info.clone());
|
self.debug_info = Some(debug_info.clone());
|
||||||
(debug_info, program_value)
|
(debug_info, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
|
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
|
||||||
@ -130,7 +131,7 @@ pub struct FunctionData {
|
|||||||
ret: Type,
|
ret: Type,
|
||||||
params: Vec<Type>,
|
params: Vec<Type>,
|
||||||
flags: FunctionFlags,
|
flags: FunctionFlags,
|
||||||
debug: Option<DebugProgramValue>,
|
meta: Option<DebugMetadataValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash)]
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
@ -169,7 +170,6 @@ impl<'ctx> Function<'ctx> {
|
|||||||
BlockData {
|
BlockData {
|
||||||
name: name.to_owned(),
|
name: name.to_owned(),
|
||||||
terminator: None,
|
terminator: None,
|
||||||
terminator_location: None,
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -177,9 +177,9 @@ impl<'ctx> Function<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_debug(&self, subprogram: DebugProgramValue) {
|
pub fn set_metadata(&self, metadata: DebugMetadataValue) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.builder.set_debug_subprogram(&self.value, subprogram);
|
self.builder.add_function_metadata(&self.value, metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,6 @@ impl<'ctx> Function<'ctx> {
|
|||||||
pub struct BlockData {
|
pub struct BlockData {
|
||||||
name: String,
|
name: String,
|
||||||
terminator: Option<TerminatorKind>,
|
terminator: Option<TerminatorKind>,
|
||||||
terminator_location: Option<DebugLocationValue>,
|
|
||||||
deleted: bool,
|
deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,10 +233,6 @@ impl<'builder> Block<'builder> {
|
|||||||
unsafe { self.builder.terminate(&self.value, instruction) }
|
unsafe { self.builder.terminate(&self.value, instruction) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_terminator_location(&mut self, location: DebugLocationValue) -> Result<(), ()> {
|
|
||||||
unsafe { self.builder.set_terminator_location(&self.value, location) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete block if it is unused. Return true if deleted, false if not.
|
/// Delete block if it is unused. Return true if deleted, false if not.
|
||||||
pub fn delete_if_unused(&mut self) -> Result<bool, ()> {
|
pub fn delete_if_unused(&mut self) -> Result<bool, ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -255,28 +250,6 @@ impl<'builder> Block<'builder> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionValue {
|
|
||||||
pub fn with_location(self, block: &Block, location: DebugLocationValue) -> InstructionValue {
|
|
||||||
unsafe {
|
|
||||||
block.builder.add_instruction_location(&self, location);
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maybe_location(
|
|
||||||
self,
|
|
||||||
block: &mut Block,
|
|
||||||
location: Option<DebugLocationValue>,
|
|
||||||
) -> InstructionValue {
|
|
||||||
unsafe {
|
|
||||||
if let Some(location) = location {
|
|
||||||
block.builder.add_instruction_location(&self, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct InstructionData {
|
pub struct InstructionData {
|
||||||
kind: Instr,
|
kind: Instr,
|
||||||
|
@ -12,6 +12,8 @@ default = ["color"]
|
|||||||
color = ["colored"]
|
color = ["colored"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
## LLVM Bindings
|
||||||
|
llvm-sys = "160"
|
||||||
## Make it easier to generate errors
|
## Make it easier to generate errors
|
||||||
thiserror = "1.0.44"
|
thiserror = "1.0.44"
|
||||||
reid-lib = { path = "../reid-llvm-lib" }
|
reid-lib = { path = "../reid-llvm-lib" }
|
||||||
|
186
reid/examples/testcodegen.rs
Normal file
186
reid/examples/testcodegen.rs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use reid::mir::{self, *};
|
||||||
|
use reid_lib::Context;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let fibonacci_name = "fibonacci".to_owned();
|
||||||
|
let fibonacci_n = "N".to_owned();
|
||||||
|
|
||||||
|
let fibonacci = FunctionDefinition {
|
||||||
|
name: fibonacci_name.clone(),
|
||||||
|
is_pub: false,
|
||||||
|
is_imported: false,
|
||||||
|
return_type: TypeKind::I32,
|
||||||
|
parameters: vec![(fibonacci_n.clone(), TypeKind::I32)],
|
||||||
|
kind: FunctionDefinitionKind::Local(
|
||||||
|
Block {
|
||||||
|
statements: vec![Statement(
|
||||||
|
StmtKind::Expression(Expression(
|
||||||
|
ExprKind::If(IfExpression(
|
||||||
|
// If N < 3
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::BinOp(
|
||||||
|
BinaryOperator::Cmp(CmpOperator::GT),
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Variable(NamedVariableRef(
|
||||||
|
TypeKind::I32,
|
||||||
|
"N".to_string(),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Literal(Literal::I32(2)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
// Then
|
||||||
|
Block {
|
||||||
|
statements: vec![],
|
||||||
|
return_expression: Some((
|
||||||
|
ReturnKind::Hard,
|
||||||
|
// return fibonacci(n-1) + fibonacci(n-2)
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::BinOp(
|
||||||
|
BinaryOperator::Add,
|
||||||
|
// fibonacci(n-1)
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::FunctionCall(FunctionCall {
|
||||||
|
name: fibonacci_name.clone(),
|
||||||
|
return_type: TypeKind::I32,
|
||||||
|
parameters: vec![Expression(
|
||||||
|
ExprKind::BinOp(
|
||||||
|
BinaryOperator::Minus,
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Variable(
|
||||||
|
NamedVariableRef(
|
||||||
|
TypeKind::I32,
|
||||||
|
fibonacci_n.clone(),
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Literal(Literal::I32(1)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)],
|
||||||
|
}),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
// fibonacci(n-2)
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::FunctionCall(FunctionCall {
|
||||||
|
name: fibonacci_name.clone(),
|
||||||
|
return_type: TypeKind::I32,
|
||||||
|
parameters: vec![Expression(
|
||||||
|
ExprKind::BinOp(
|
||||||
|
BinaryOperator::Minus,
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Variable(
|
||||||
|
NamedVariableRef(
|
||||||
|
TypeKind::I32,
|
||||||
|
fibonacci_n.clone(),
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Literal(Literal::I32(2)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)],
|
||||||
|
}),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
meta: Default::default(),
|
||||||
|
},
|
||||||
|
// No else-block
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
Default::default(),
|
||||||
|
)],
|
||||||
|
// return 1
|
||||||
|
return_expression: Some((
|
||||||
|
ReturnKind::Soft,
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::Literal(Literal::I32(1)),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
meta: Default::default(),
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let main = FunctionDefinition {
|
||||||
|
name: "main".to_owned(),
|
||||||
|
is_pub: false,
|
||||||
|
is_imported: false,
|
||||||
|
return_type: TypeKind::I32,
|
||||||
|
parameters: vec![],
|
||||||
|
kind: FunctionDefinitionKind::Local(
|
||||||
|
Block {
|
||||||
|
statements: vec![],
|
||||||
|
return_expression: Some((
|
||||||
|
ReturnKind::Soft,
|
||||||
|
Box::new(Expression(
|
||||||
|
ExprKind::FunctionCall(FunctionCall {
|
||||||
|
name: fibonacci_name.clone(),
|
||||||
|
return_type: TypeKind::I32,
|
||||||
|
parameters: vec![Expression(
|
||||||
|
ExprKind::Literal(Literal::I32(5)),
|
||||||
|
Default::default(),
|
||||||
|
)],
|
||||||
|
}),
|
||||||
|
Default::default(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
meta: Default::default(),
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mir_context = mir::Context {
|
||||||
|
modules: vec![Module {
|
||||||
|
name: "test module".to_owned(),
|
||||||
|
module_id: SourceModuleId::default(),
|
||||||
|
imports: vec![],
|
||||||
|
functions: vec![fibonacci, main],
|
||||||
|
typedefs: Vec::new(),
|
||||||
|
path: None,
|
||||||
|
is_main: true,
|
||||||
|
}],
|
||||||
|
base: PathBuf::new(),
|
||||||
|
};
|
||||||
|
println!("test1");
|
||||||
|
|
||||||
|
let context = Context::new();
|
||||||
|
let codegen = mir_context.codegen(&context);
|
||||||
|
println!("test2");
|
||||||
|
|
||||||
|
codegen.compile();
|
||||||
|
println!("test3");
|
||||||
|
|
||||||
|
// match codegen_module.module.print_to_string() {
|
||||||
|
// Ok(v) => println!("{}", v),
|
||||||
|
// Err(e) => println!("Err: {:?}", e),
|
||||||
|
// }
|
||||||
|
}
|
@ -4,22 +4,15 @@ use reid_lib::{
|
|||||||
builder::{InstructionValue, TypeValue},
|
builder::{InstructionValue, TypeValue},
|
||||||
compile::CompiledModule,
|
compile::CompiledModule,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugBasicType, DebugFileData, DebugInformation, DebugLocation, DebugMetadata,
|
AteEncoding, DebugBasicType, DebugFileData, DebugFunction, DebugInformation, DebugLocation,
|
||||||
DebugMetadataValue, DebugParamVariable, DebugProgramValue, DebugScopeValue,
|
DebugMetadata, DebugMetadataValue, DebugScopeValue,
|
||||||
DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramTypeData, 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::{
|
use crate::mir::{
|
||||||
error_raporting::ModuleMap,
|
self, NamedVariableRef, StructField, StructType, TypeDefinitionKind, TypeKind, VagueLiteral,
|
||||||
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
|
||||||
@ -39,24 +32,10 @@ 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>(
|
pub fn codegen<'ctx>(&self, context: &'ctx Context) -> CodegenContext<'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(
|
modules.push(module.codegen(context));
|
||||||
module.codegen(
|
|
||||||
context,
|
|
||||||
mod_map
|
|
||||||
.module(&module.module_id)
|
|
||||||
.unwrap()
|
|
||||||
.tokens
|
|
||||||
.as_ref()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
CodegenContext { context }
|
CodegenContext { context }
|
||||||
}
|
}
|
||||||
@ -74,26 +53,16 @@ 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 StackFunction<'ctx>,
|
function: &'ctx Function<'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, StackFunction<'ctx>>,
|
functions: &'a HashMap<String, Function<'ctx>>,
|
||||||
stack_values: HashMap<String, StackValue>,
|
stack_values: HashMap<String, StackValue>,
|
||||||
debug: Option<Debug<'ctx>>,
|
debug: &'ctx DebugInformation,
|
||||||
debug_const_tys: &'a HashMap<TypeKind, DebugTypeValue>,
|
debug_scope: DebugScopeValue,
|
||||||
}
|
debug_const_tys: &'a HashMap<TypeKind, DebugMetadataValue>,
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Debug<'ctx> {
|
|
||||||
info: &'ctx DebugInformation,
|
|
||||||
scope: DebugProgramValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct StackFunction<'ctx> {
|
|
||||||
ir: Function<'ctx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -110,7 +79,6 @@ 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,
|
||||||
@ -118,7 +86,8 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
types: self.types,
|
types: self.types,
|
||||||
type_values: self.type_values,
|
type_values: self.type_values,
|
||||||
stack_values: self.stack_values.clone(),
|
stack_values: self.stack_values.clone(),
|
||||||
debug: self.debug.clone(),
|
debug: self.debug,
|
||||||
|
debug_scope: self.debug_scope.clone(),
|
||||||
debug_const_tys: self.debug_const_tys,
|
debug_const_tys: self.debug_const_tys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,14 +126,10 @@ impl Default for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Module {
|
impl mir::Module {
|
||||||
fn codegen<'ctx>(
|
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'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, compile_unit) = if let Some(path) = &self.path {
|
let (debug, debug_scope) = if let Some(path) = &self.path {
|
||||||
module.create_debug_info(DebugFileData {
|
module.create_debug_info(DebugFileData {
|
||||||
name: path.file_name().unwrap().to_str().unwrap().to_owned(),
|
name: path.file_name().unwrap().to_str().unwrap().to_owned(),
|
||||||
directory: path.parent().unwrap().to_str().unwrap().to_owned(),
|
directory: path.parent().unwrap().to_str().unwrap().to_owned(),
|
||||||
@ -182,12 +147,14 @@ impl mir::Module {
|
|||||||
|
|
||||||
debug_const_types.insert(
|
debug_const_types.insert(
|
||||||
TypeKind::U32,
|
TypeKind::U32,
|
||||||
debug.debug_type(DebugTypeData::Basic(DebugBasicType {
|
debug.metadata(
|
||||||
name: String::from("u32"),
|
&debug_scope,
|
||||||
size_bits: 32,
|
DebugMetadata::BasicType(DebugBasicType {
|
||||||
encoding: DwarfEncoding::Unsigned,
|
name: String::from("u32"),
|
||||||
flags: DwarfFlags,
|
size_bits: 32,
|
||||||
})),
|
encoding: AteEncoding::Unsigned,
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
for typedef in &self.typedefs {
|
for typedef in &self.typedefs {
|
||||||
@ -242,49 +209,15 @@ impl mir::Module {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
functions.insert(function.name.clone(), func);
|
||||||
functions.insert(function.name.clone(), StackFunction { ir: func });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.ir.block("entry");
|
let mut entry = function.block("entry");
|
||||||
|
|
||||||
// Insert debug information
|
|
||||||
let debug_scope = if let Some(location) = mir_function.signature().into_debug(tokens) {
|
|
||||||
// let debug_scope = debug.inner_scope(&outer_scope, location);
|
|
||||||
|
|
||||||
let fn_param_ty = debug_const_types.get(&TypeKind::U32).unwrap();
|
|
||||||
|
|
||||||
let debug_ty =
|
|
||||||
debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramTypeData {
|
|
||||||
parameters: vec![*fn_param_ty],
|
|
||||||
flags: DwarfFlags,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let subprogram = debug.subprogram(DebugSubprogramData {
|
|
||||||
name: mir_function.name.clone(),
|
|
||||||
outer_scope: compile_unit.clone(),
|
|
||||||
location,
|
|
||||||
ty: debug_ty,
|
|
||||||
opts: DebugSubprogramOptionals {
|
|
||||||
is_local: !mir_function.is_pub,
|
|
||||||
is_definition: true,
|
|
||||||
..DebugSubprogramOptionals::default()
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function.ir.set_debug(subprogram);
|
|
||||||
|
|
||||||
Some(subprogram)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Compile actual IR part
|
|
||||||
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() {
|
||||||
// Codegen actual parameters
|
|
||||||
stack_values.insert(
|
stack_values.insert(
|
||||||
p_name.clone(),
|
p_name.clone(),
|
||||||
StackValue(
|
StackValue(
|
||||||
@ -292,28 +225,10 @@ impl mir::Module {
|
|||||||
p_ty.get_type(&type_values, &types),
|
p_ty.get_type(&type_values, &types),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Generate debug info
|
|
||||||
if let (Some(debug_scope), Some(location)) =
|
|
||||||
(&debug_scope, mir_function.signature().into_debug(tokens))
|
|
||||||
{
|
|
||||||
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,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scope = Scope {
|
let mut scope = Scope {
|
||||||
context,
|
context,
|
||||||
tokens,
|
|
||||||
module: &module,
|
module: &module,
|
||||||
function,
|
function,
|
||||||
block: entry,
|
block: entry,
|
||||||
@ -321,15 +236,10 @@ impl mir::Module {
|
|||||||
types: &types,
|
types: &types,
|
||||||
type_values: &type_values,
|
type_values: &type_values,
|
||||||
stack_values,
|
stack_values,
|
||||||
debug: debug_scope.and_then(|scope| {
|
debug: &debug,
|
||||||
Some(Debug {
|
debug_scope: debug_scope.clone(),
|
||||||
info: &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();
|
||||||
@ -343,11 +253,22 @@ impl mir::Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(debug) = scope.debug {
|
let fn_return_ty = debug_const_types.get(&TypeKind::U32).unwrap();
|
||||||
let location = &block.return_meta().into_debug(tokens).unwrap();
|
|
||||||
let location = debug.info.location(&debug.scope, *location);
|
scope.function.set_metadata(scope.debug.metadata(
|
||||||
scope.block.set_terminator_location(location).unwrap();
|
&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(_) => {}
|
||||||
}
|
}
|
||||||
@ -364,13 +285,7 @@ impl mir::Block {
|
|||||||
state: &State,
|
state: &State,
|
||||||
) -> Option<InstructionValue> {
|
) -> Option<InstructionValue> {
|
||||||
for stmt in &self.statements {
|
for stmt in &self.statements {
|
||||||
stmt.codegen(&mut scope, state).map(|s| {
|
stmt.codegen(&mut scope, state);
|
||||||
if let Some(debug) = &scope.debug {
|
|
||||||
let location = stmt.1.into_debug(scope.tokens).unwrap();
|
|
||||||
let loc_val = debug.info.location(&debug.scope, location);
|
|
||||||
s.with_location(&mut scope.block, loc_val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((kind, expr)) = &self.return_expression {
|
if let Some((kind, expr)) = &self.return_expression {
|
||||||
@ -457,16 +372,6 @@ impl mir::Expression {
|
|||||||
scope: &mut Scope<'ctx, 'a>,
|
scope: &mut Scope<'ctx, 'a>,
|
||||||
state: &State,
|
state: &State,
|
||||||
) -> Option<InstructionValue> {
|
) -> Option<InstructionValue> {
|
||||||
let location = if let Some(debug) = &scope.debug {
|
|
||||||
Some(
|
|
||||||
debug
|
|
||||||
.info
|
|
||||||
.location(&debug.scope, self.1.into_debug(scope.tokens).unwrap()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
mir::ExprKind::Variable(varref) => {
|
mir::ExprKind::Variable(varref) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
varref.0.known().expect("variable type unknown");
|
||||||
@ -539,13 +444,13 @@ impl mir::Expression {
|
|||||||
Some(
|
Some(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::FunctionCall(callee.ir.value(), params))
|
.build(Instr::FunctionCall(callee.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.ir.block("inner"));
|
let mut inner_scope = scope.with_block(scope.function.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
|
||||||
@ -670,7 +575,6 @@ impl mir::Expression {
|
|||||||
Some(struct_ptr)
|
Some(struct_ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map(|i| i.maybe_location(&mut scope.block, location))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,27 +587,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 mut then_b = scope.function.ir.block("then");
|
let then_b = scope.function.block("then");
|
||||||
let mut else_b = scope.function.ir.block("else");
|
let mut else_b = scope.function.block("else");
|
||||||
let after_b = scope.function.ir.block("after");
|
let after_b = scope.function.block("after");
|
||||||
|
|
||||||
if let Some(debug) = &scope.debug {
|
|
||||||
let before_location = self.0 .1.into_debug(scope.tokens).unwrap();
|
|
||||||
let before_v = debug.info.location(&debug.scope, before_location);
|
|
||||||
scope.block.set_terminator_location(before_v).unwrap();
|
|
||||||
|
|
||||||
let then_location = self.1.return_meta().into_debug(scope.tokens).unwrap();
|
|
||||||
let then_v = debug.info.location(&debug.scope, then_location);
|
|
||||||
then_b.set_terminator_location(then_v).unwrap();
|
|
||||||
|
|
||||||
let else_location = if let Some(else_block) = &self.2 {
|
|
||||||
else_block.return_meta().into_debug(scope.tokens).unwrap()
|
|
||||||
} else {
|
|
||||||
then_location
|
|
||||||
};
|
|
||||||
let else_v = debug.info.location(&debug.scope, else_location);
|
|
||||||
else_b.set_terminator_location(else_v).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store for convenience
|
// Store for convenience
|
||||||
let then_bb = then_b.value();
|
let then_bb = then_b.value();
|
||||||
@ -717,7 +603,6 @@ impl mir::IfExpression {
|
|||||||
|
|
||||||
let else_res = if let Some(else_block) = &self.2 {
|
let else_res = if let Some(else_block) = &self.2 {
|
||||||
let mut else_scope = scope.with_block(else_b);
|
let mut else_scope = scope.with_block(else_b);
|
||||||
|
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.terminate(Term::CondBr(condition, then_bb, else_bb))
|
.terminate(Term::CondBr(condition, then_bb, else_bb))
|
||||||
@ -824,22 +709,3 @@ 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 Module {
|
pub struct ErrModule {
|
||||||
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 Module {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
pub struct ModuleMap {
|
pub struct ModuleMap {
|
||||||
module_map: HashMap<mir::SourceModuleId, Module>,
|
module_map: HashMap<mir::SourceModuleId, ErrModule>,
|
||||||
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,
|
||||||
Module {
|
ErrModule {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
source: None,
|
source: None,
|
||||||
@ -107,7 +107,7 @@ impl ModuleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(&self, id: &mir::SourceModuleId) -> Option<&Module> {
|
pub fn get_module(&self, id: &mir::SourceModuleId) -> Option<&ErrModule> {
|
||||||
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.module(&meta.source_module_id).unwrap();
|
let module = self.map.get_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.module(&module_id).cloned().unwrap();
|
let module = map.get_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(format!("Reid ({})", env!("CARGO_PKG_VERSION")));
|
let mut context = Context::new();
|
||||||
let codegen_modules = mir_context.codegen(&mut context, &module_map);
|
let codegen_modules = mir_context.codegen(&mut context);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&codegen_modules);
|
dbg!(&codegen_modules);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use reid_lib::debug_information::DebugLocation;
|
|
||||||
|
|
||||||
use super::{typecheck::ErrorKind, typerefs::TypeRefs, VagueType as Vague, *};
|
use super::{typecheck::ErrorKind, typerefs::TypeRefs, VagueType as Vague, *};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -71,14 +69,6 @@ impl Block {
|
|||||||
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta))
|
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_meta(&self) -> Metadata {
|
|
||||||
self.return_expression
|
|
||||||
.as_ref()
|
|
||||||
.map(|e| e.1 .1)
|
|
||||||
.or(self.statements.last().map(|s| s.1))
|
|
||||||
.unwrap_or(self.meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
|
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
|
||||||
let mut early_return = None;
|
let mut early_return = None;
|
||||||
|
|
||||||
|
@ -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
|
||||||
.module(&module.module_id)
|
.get_module(&module.module_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.tokens
|
.tokens
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{lexer::Position, token_stream::TokenRange};
|
||||||
lexer::{FullToken, Position},
|
|
||||||
token_stream::TokenRange,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
pub mod r#impl;
|
pub mod r#impl;
|
||||||
@ -39,19 +36,6 @@ 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_or(first);
|
|
||||||
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 {
|
||||||
@ -264,9 +248,7 @@ 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)>,
|
||||||
@ -282,14 +264,14 @@ pub enum FunctionDefinitionKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionDefinition {
|
impl FunctionDefinition {
|
||||||
pub fn block_meta(&self) -> Metadata {
|
fn block_meta(&self) -> Metadata {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
FunctionDefinitionKind::Local(block, _) => block.meta.clone(),
|
FunctionDefinitionKind::Local(block, _) => block.meta.clone(),
|
||||||
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn signature(&self) -> Metadata {
|
fn signature(&self) -> Metadata {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
FunctionDefinitionKind::Local(_, metadata) => metadata.clone(),
|
FunctionDefinitionKind::Local(_, metadata) => metadata.clone(),
|
||||||
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
FunctionDefinitionKind::Extern(_) => Metadata::default(),
|
||||||
|
Loading…
Reference in New Issue
Block a user