Compare commits
10 Commits
33ed1fd813
...
f700c577f1
Author | SHA1 | Date | |
---|---|---|---|
f700c577f1 | |||
ebe7fc8d75 | |||
140d963d9b | |||
480ba5155a | |||
2207c3df83 | |||
735c3231b1 | |||
50a875ad21 | |||
30257e1a2b | |||
a7ac974f46 | |||
3d8f4bbd24 |
@ -1,3 +1,5 @@
|
|||||||
fn main() -> u32 {
|
fn main() -> u8 {
|
||||||
return test_macro!();
|
// let message = String::from(include_bytes!("./macro_easy_file.txt"));
|
||||||
}
|
let bytes = test_macro!("./examples/macro_easy_file.txt");
|
||||||
|
return bytes[0];
|
||||||
|
}
|
||||||
|
1
examples/macro_easy_file.txt
Normal file
1
examples/macro_easy_file.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
hello
|
@ -1,7 +1,7 @@
|
|||||||
use reid_lib::{CmpPredicate, ConstValue, Context, FunctionFlags, Instr, TerminatorKind, Type};
|
use reid_lib::{CmpPredicate, ConstValueKind, Context, FunctionFlags, Instr, TerminatorKind, Type};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use ConstValue::*;
|
use ConstValueKind::*;
|
||||||
use Instr::*;
|
use Instr::*;
|
||||||
|
|
||||||
let context = Context::new("libtest");
|
let context = Context::new("libtest");
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, ModuleData,
|
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData,
|
||||||
NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData,
|
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData,
|
||||||
},
|
},
|
||||||
@ -27,6 +27,12 @@ pub struct BlockValue(pub(crate) FunctionValue, pub(crate) usize);
|
|||||||
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
||||||
pub struct InstructionValue(pub(crate) BlockValue, pub(crate) usize);
|
pub struct InstructionValue(pub(crate) BlockValue, pub(crate) usize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, Copy, PartialEq, Eq)]
|
||||||
|
pub struct ConstantValue(pub(crate) ModuleValue, pub(crate) usize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, Copy, PartialEq, Eq)]
|
||||||
|
pub struct GlobalValue(pub(crate) ModuleValue, pub(crate) usize);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ModuleHolder {
|
pub struct ModuleHolder {
|
||||||
pub(crate) value: ModuleValue,
|
pub(crate) value: ModuleValue,
|
||||||
@ -34,6 +40,20 @@ pub struct ModuleHolder {
|
|||||||
pub(crate) functions: Vec<FunctionHolder>,
|
pub(crate) functions: Vec<FunctionHolder>,
|
||||||
pub(crate) types: Vec<TypeHolder>,
|
pub(crate) types: Vec<TypeHolder>,
|
||||||
pub(crate) debug_information: Option<DebugInformation>,
|
pub(crate) debug_information: Option<DebugInformation>,
|
||||||
|
pub(crate) constants: Vec<ConstantValueHolder>,
|
||||||
|
pub(crate) globals: Vec<GlobalValueHolder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ConstantValueHolder {
|
||||||
|
pub(crate) value: ConstantValue,
|
||||||
|
pub(crate) kind: ConstValueKind,
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GlobalValueHolder {
|
||||||
|
pub(crate) value: GlobalValue,
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) initializer: ConstantValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -88,6 +108,8 @@ impl Builder {
|
|||||||
functions: Vec::new(),
|
functions: Vec::new(),
|
||||||
types: Vec::new(),
|
types: Vec::new(),
|
||||||
debug_information: None,
|
debug_information: None,
|
||||||
|
constants: Vec::new(),
|
||||||
|
globals: Vec::new(),
|
||||||
});
|
});
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
@ -168,6 +190,35 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn build_constant(&self, module: ModuleValue, kind: ConstValueKind) -> ConstantValue {
|
||||||
|
unsafe {
|
||||||
|
let mut modules = self.modules.borrow_mut();
|
||||||
|
let module = modules.get_unchecked_mut(module.0);
|
||||||
|
let value = ConstantValue(module.value, module.constants.len());
|
||||||
|
module.constants.push(ConstantValueHolder { value, kind });
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn add_global(
|
||||||
|
&self,
|
||||||
|
module: ModuleValue,
|
||||||
|
name: String,
|
||||||
|
initializer: ConstantValue,
|
||||||
|
) -> GlobalValue {
|
||||||
|
unsafe {
|
||||||
|
let mut modules = self.modules.borrow_mut();
|
||||||
|
let module = modules.get_unchecked_mut(module.0);
|
||||||
|
let value = GlobalValue(module.value, module.globals.len());
|
||||||
|
module.globals.push(GlobalValueHolder {
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
initializer,
|
||||||
|
});
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn find_function(&self, module: ModuleValue, name: &String) -> Option<FunctionValue> {
|
pub(crate) unsafe fn find_function(&self, module: ModuleValue, name: &String) -> Option<FunctionValue> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
@ -332,6 +383,24 @@ impl Builder {
|
|||||||
self.modules.clone()
|
self.modules.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_global_initializer(&self, value: GlobalValue) -> ConstantValue {
|
||||||
|
unsafe {
|
||||||
|
let modules = self.modules.borrow();
|
||||||
|
let module = modules.get_unchecked(value.0.0);
|
||||||
|
let global = module.globals.get_unchecked(value.1);
|
||||||
|
global.initializer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_const_kind(&self, value: ConstantValue) -> ConstValueKind {
|
||||||
|
unsafe {
|
||||||
|
let modules = self.modules.borrow();
|
||||||
|
let module = modules.get_unchecked(value.0.0);
|
||||||
|
let constant = module.constants.get_unchecked(value.1);
|
||||||
|
constant.kind.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_instruction(&self, instruction: &InstructionValue) -> CompileResult<()> {
|
pub fn check_instruction(&self, instruction: &InstructionValue) -> CompileResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.instr_data(&instruction).kind {
|
match self.instr_data(&instruction).kind {
|
||||||
@ -566,6 +635,7 @@ impl Builder {
|
|||||||
Err(ErrorKind::Null)
|
Err(ErrorKind::Null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Instr::GetGlobal(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -717,6 +787,11 @@ impl InstructionValue {
|
|||||||
ShiftRightLogical(lhs, _) => lhs.get_type(builder),
|
ShiftRightLogical(lhs, _) => lhs.get_type(builder),
|
||||||
ShiftRightArithmetic(lhs, _) => lhs.get_type(builder),
|
ShiftRightArithmetic(lhs, _) => lhs.get_type(builder),
|
||||||
ShiftLeft(lhs, _) => lhs.get_type(builder),
|
ShiftLeft(lhs, _) => lhs.get_type(builder),
|
||||||
|
GetGlobal(global_value) => {
|
||||||
|
let constant = builder.get_global_initializer(*global_value);
|
||||||
|
let kind = builder.get_const_kind(constant);
|
||||||
|
Ok(kind.get_type())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,13 @@ use llvm_sys::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CustomTypeKind,
|
CustomTypeKind,
|
||||||
builder::{TypeHolder, TypeValue},
|
builder::{ConstantValue, GlobalValue, TypeHolder, TypeValue},
|
||||||
debug_information::*,
|
debug_information::*,
|
||||||
util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring},
|
util::{ErrorMessageHolder, MemoryBufferHolder, from_cstring, into_cstring},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
CmpPredicate, ConstValue, Context, TerminatorKind, Type,
|
CmpPredicate, ConstValueKind, Context, TerminatorKind, Type,
|
||||||
builder::{
|
builder::{
|
||||||
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue,
|
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue,
|
||||||
ModuleHolder,
|
ModuleHolder,
|
||||||
@ -193,6 +193,8 @@ 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>,
|
||||||
|
constants: HashMap<ConstantValue, LLVMValue>,
|
||||||
|
globals: HashMap<GlobalValue, LLVMValueRef>,
|
||||||
debug: Option<LLVMDebugInformation<'a>>,
|
debug: Option<LLVMDebugInformation<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +239,8 @@ impl ModuleHolder {
|
|||||||
// Compile the contents
|
// Compile the contents
|
||||||
|
|
||||||
let mut types = HashMap::new();
|
let mut types = HashMap::new();
|
||||||
|
let mut constants = HashMap::new();
|
||||||
|
let mut globals = HashMap::new();
|
||||||
let mut metadata = HashMap::new();
|
let mut metadata = HashMap::new();
|
||||||
let mut scopes = HashMap::new();
|
let mut scopes = HashMap::new();
|
||||||
let mut locations = HashMap::new();
|
let mut locations = HashMap::new();
|
||||||
@ -320,6 +324,29 @@ impl ModuleHolder {
|
|||||||
types.insert(ty.value, ty.compile_type(context, &types));
|
types.insert(ty.value, ty.compile_type(context, &types));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for constant in &self.constants {
|
||||||
|
constants.insert(
|
||||||
|
constant.value,
|
||||||
|
LLVMValue {
|
||||||
|
ty: constant.kind.get_type(),
|
||||||
|
value_ref: constant
|
||||||
|
.kind
|
||||||
|
.as_llvm(context.context_ref, context.builder_ref, &constants, &types),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for global in &self.globals {
|
||||||
|
let initializer = constants.get(&global.initializer).expect("No initializer?");
|
||||||
|
let global_value = LLVMAddGlobal(
|
||||||
|
module_ref,
|
||||||
|
initializer.ty.as_llvm(context.context_ref, &types),
|
||||||
|
into_cstring(global.name.clone()).as_ptr(),
|
||||||
|
);
|
||||||
|
LLVMSetInitializer(global_value, initializer.value_ref);
|
||||||
|
globals.insert(global.value, global_value);
|
||||||
|
}
|
||||||
|
|
||||||
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, &mut debug);
|
let func = function.compile_signature(context, module_ref, &types, &mut debug);
|
||||||
@ -358,6 +385,8 @@ impl ModuleHolder {
|
|||||||
types,
|
types,
|
||||||
blocks: HashMap::new(),
|
blocks: HashMap::new(),
|
||||||
values: HashMap::new(),
|
values: HashMap::new(),
|
||||||
|
constants,
|
||||||
|
globals,
|
||||||
debug,
|
debug,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -732,7 +761,7 @@ impl InstructionHolder {
|
|||||||
use super::Instr::*;
|
use super::Instr::*;
|
||||||
match &self.data.kind {
|
match &self.data.kind {
|
||||||
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32),
|
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32),
|
||||||
Constant(val) => val.as_llvm(module),
|
Constant(val) => val.as_llvm(module.context_ref, module.builder_ref, &module.constants, &module.types),
|
||||||
Add(lhs, rhs) => {
|
Add(lhs, rhs) => {
|
||||||
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
|
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
|
||||||
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
||||||
@ -1023,6 +1052,7 @@ impl InstructionHolder {
|
|||||||
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
||||||
LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
|
LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
|
||||||
}
|
}
|
||||||
|
GetGlobal(global_value) => module.globals.get(global_value).unwrap().clone(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(record) = &self.record {
|
if let Some(record) = &self.record {
|
||||||
@ -1144,32 +1174,50 @@ impl CmpPredicate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstValue {
|
impl ConstValueKind {
|
||||||
fn as_llvm(&self, module: &LLVMModule) -> LLVMValueRef {
|
fn as_llvm(
|
||||||
|
&self,
|
||||||
|
context: LLVMContextRef,
|
||||||
|
builder: LLVMBuilderRef,
|
||||||
|
constants: &HashMap<ConstantValue, LLVMValue>,
|
||||||
|
types: &HashMap<TypeValue, LLVMTypeRef>,
|
||||||
|
) -> LLVMValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let t = self.get_type().as_llvm(module.context_ref, &module.types);
|
let t = self.get_type().as_llvm(context, &types);
|
||||||
match self {
|
match self {
|
||||||
ConstValue::Bool(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::Bool(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I8(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::I8(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I16(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::I16(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I32(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::I32(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I64(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::I64(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::I128(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::I128(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::U8(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::U8(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::U16(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::U16(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::U32(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::U64(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1),
|
ConstValueKind::U128(val) => LLVMConstInt(t, *val as u64, 1),
|
||||||
ConstValue::Str(val) => {
|
ConstValueKind::Str(val) => {
|
||||||
LLVMBuildGlobalString(module.builder_ref, into_cstring(val).as_ptr(), c"string".as_ptr())
|
LLVMBuildGlobalString(builder, into_cstring(val).as_ptr(), c"string".as_ptr())
|
||||||
|
}
|
||||||
|
ConstValueKind::F16(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F32B(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F32(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F64(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F80(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F128(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::F128PPC(val) => LLVMConstReal(t, *val as f64),
|
||||||
|
ConstValueKind::Array(constant_values, elem_ty) => {
|
||||||
|
let mut values = constant_values
|
||||||
|
.iter()
|
||||||
|
.map(|v| constants.get(v).unwrap().value_ref)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
LLVMConstArray2(
|
||||||
|
elem_ty.as_llvm(context, &types),
|
||||||
|
values.as_mut_ptr(),
|
||||||
|
values.len() as u64,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ConstValue::F16(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F32B(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F32(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F64(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F80(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F128(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
ConstValue::F128PPC(val) => LLVMConstReal(t, *val as f64),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,6 +392,7 @@ impl Debug for Instr {
|
|||||||
Instr::ShiftRightLogical(lhs, rhs) => fmt_binop(f, lhs, &">>l", rhs),
|
Instr::ShiftRightLogical(lhs, rhs) => fmt_binop(f, lhs, &">>l", rhs),
|
||||||
Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs),
|
Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs),
|
||||||
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
|
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
|
||||||
|
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,10 @@ use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue,
|
|||||||
use debug_information::{DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue};
|
use debug_information::{DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue};
|
||||||
use fmt::PrintableModule;
|
use fmt::PrintableModule;
|
||||||
|
|
||||||
use crate::debug_information::DebugScopeValue;
|
use crate::{
|
||||||
|
builder::{ConstantValue, GlobalValue},
|
||||||
|
debug_information::DebugScopeValue,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod compile;
|
pub mod compile;
|
||||||
@ -121,6 +124,14 @@ impl<'ctx> Module<'ctx> {
|
|||||||
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
|
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
|
||||||
&self.debug_info
|
&self.debug_info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_constant(&self, constant: ConstValueKind) -> ConstantValue {
|
||||||
|
unsafe { self.builder.build_constant(self.value, constant) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_global<T: Into<String>>(&self, name: T, constant: ConstantValue) -> GlobalValue {
|
||||||
|
unsafe { self.builder.add_global(self.value, name.into(), constant) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> Drop for Module<'ctx> {
|
impl<'ctx> Drop for Module<'ctx> {
|
||||||
@ -265,6 +276,7 @@ impl Instr {
|
|||||||
Instr::ShiftRightLogical(..) => "lshr",
|
Instr::ShiftRightLogical(..) => "lshr",
|
||||||
Instr::ShiftRightArithmetic(..) => "ashr",
|
Instr::ShiftRightArithmetic(..) => "ashr",
|
||||||
Instr::ShiftLeft(..) => "shl",
|
Instr::ShiftLeft(..) => "shl",
|
||||||
|
Instr::GetGlobal(..) => "global",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,7 +373,8 @@ pub enum CmpPredicate {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Instr {
|
pub enum Instr {
|
||||||
Param(usize),
|
Param(usize),
|
||||||
Constant(ConstValue),
|
Constant(ConstValueKind),
|
||||||
|
GetGlobal(GlobalValue),
|
||||||
|
|
||||||
/// Add two integers
|
/// Add two integers
|
||||||
Add(InstructionValue, InstructionValue),
|
Add(InstructionValue, InstructionValue),
|
||||||
@ -487,7 +500,7 @@ pub enum Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ConstValue {
|
pub enum ConstValueKind {
|
||||||
I8(i8),
|
I8(i8),
|
||||||
I16(i16),
|
I16(i16),
|
||||||
I32(i32),
|
I32(i32),
|
||||||
@ -507,6 +520,7 @@ pub enum ConstValue {
|
|||||||
F80(f64),
|
F80(f64),
|
||||||
F128(f64),
|
F128(f64),
|
||||||
F128PPC(f64),
|
F128PPC(f64),
|
||||||
|
Array(Vec<ConstantValue>, Type),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
@ -531,29 +545,30 @@ pub enum CustomTypeKind {
|
|||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
pub struct NamedStruct(pub String, pub Vec<Type>);
|
pub struct NamedStruct(pub String, pub Vec<Type>);
|
||||||
|
|
||||||
impl ConstValue {
|
impl ConstValueKind {
|
||||||
pub fn get_type(&self) -> Type {
|
pub fn get_type(&self) -> Type {
|
||||||
use Type::*;
|
use Type::*;
|
||||||
match self {
|
match self {
|
||||||
ConstValue::I8(_) => I8,
|
ConstValueKind::I8(_) => I8,
|
||||||
ConstValue::I16(_) => I16,
|
ConstValueKind::I16(_) => I16,
|
||||||
ConstValue::I32(_) => I32,
|
ConstValueKind::I32(_) => I32,
|
||||||
ConstValue::I64(_) => I64,
|
ConstValueKind::I64(_) => I64,
|
||||||
ConstValue::I128(_) => I128,
|
ConstValueKind::I128(_) => I128,
|
||||||
ConstValue::U8(_) => U8,
|
ConstValueKind::U8(_) => U8,
|
||||||
ConstValue::U16(_) => U16,
|
ConstValueKind::U16(_) => U16,
|
||||||
ConstValue::U32(_) => U32,
|
ConstValueKind::U32(_) => U32,
|
||||||
ConstValue::U64(_) => U64,
|
ConstValueKind::U64(_) => U64,
|
||||||
ConstValue::U128(_) => U128,
|
ConstValueKind::U128(_) => U128,
|
||||||
ConstValue::Str(_) => Type::Ptr(Box::new(U8)),
|
ConstValueKind::Str(_) => Type::Ptr(Box::new(U8)),
|
||||||
ConstValue::Bool(_) => Bool,
|
ConstValueKind::Bool(_) => Bool,
|
||||||
ConstValue::F16(_) => F16,
|
ConstValueKind::F16(_) => F16,
|
||||||
ConstValue::F32B(_) => F32B,
|
ConstValueKind::F32B(_) => F32B,
|
||||||
ConstValue::F32(_) => F32,
|
ConstValueKind::F32(_) => F32,
|
||||||
ConstValue::F64(_) => F64,
|
ConstValueKind::F64(_) => F64,
|
||||||
ConstValue::F80(_) => F80,
|
ConstValueKind::F80(_) => F80,
|
||||||
ConstValue::F128(_) => F128,
|
ConstValueKind::F128(_) => F128,
|
||||||
ConstValue::F128PPC(_) => F128PPC,
|
ConstValueKind::F128PPC(_) => F128PPC,
|
||||||
|
ConstValueKind::Array(vals, ty) => Type::Array(Box::new(ty.clone()), vals.len() as u64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ impl ast::Module {
|
|||||||
imports,
|
imports,
|
||||||
associated_functions,
|
associated_functions,
|
||||||
functions,
|
functions,
|
||||||
|
globals: Vec::new(),
|
||||||
path: self.path.clone(),
|
path: self.path.clone(),
|
||||||
is_main: self.is_main,
|
is_main: self.is_main,
|
||||||
tokens: self.tokens,
|
tokens: self.tokens,
|
||||||
|
@ -195,6 +195,7 @@ impl mir::Expression {
|
|||||||
mir::ExprKind::AssociatedFunctionCall(ty, fn_call) => {
|
mir::ExprKind::AssociatedFunctionCall(ty, fn_call) => {
|
||||||
allocated.extend(fn_call.allocate(&format!("{}::{}", ty, fn_call.name), scope))
|
allocated.extend(fn_call.allocate(&format!("{}::{}", ty, fn_call.name), scope))
|
||||||
}
|
}
|
||||||
|
mir::ExprKind::GlobalRef(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
allocated
|
allocated
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr, Type};
|
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{ErrorKind, StackValueKind},
|
codegen::{ErrorKind, StackValueKind},
|
||||||
mir::{
|
mir::{
|
||||||
self, BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, FunctionDefinitionKind, FunctionParam,
|
BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, FunctionDefinitionKind, FunctionParam,
|
||||||
TypeKind,
|
TypeKind,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -309,14 +309,6 @@ pub trait IntrinsicFunction: std::fmt::Debug {
|
|||||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind>;
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MacroFunction: std::fmt::Debug {
|
|
||||||
fn generate<'ctx, 'a>(
|
|
||||||
&self,
|
|
||||||
scope: &mut Scope<'ctx, 'a>,
|
|
||||||
params: &[mir::Literal],
|
|
||||||
) -> Result<mir::Expression, ErrorKind>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! intrinsic_debug {
|
macro_rules! intrinsic_debug {
|
||||||
($kind:ty, $name:literal) => {
|
($kind:ty, $name:literal) => {
|
||||||
impl<T> std::fmt::Debug for $kind
|
impl<T> std::fmt::Debug for $kind
|
||||||
@ -372,7 +364,7 @@ impl IntrinsicFunction for IntrinsicSizeOf {
|
|||||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
||||||
let instr = scope
|
let instr = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Constant(reid_lib::ConstValue::U64(self.0.size_of() / 8)))
|
.build(Instr::Constant(reid_lib::ConstValueKind::U64(self.0.size_of() / 8)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
|
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
|
||||||
}
|
}
|
||||||
@ -390,7 +382,7 @@ impl IntrinsicFunction for IntrinsicMalloc {
|
|||||||
|
|
||||||
let sizeof = scope
|
let sizeof = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Constant(ConstValue::U64(self.0.size_of() / 8)))
|
.build(Instr::Constant(ConstValueKind::U64(self.0.size_of() / 8)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let bytes = scope.block.build(Instr::Mul(sizeof, amount.instr())).unwrap();
|
let bytes = scope.block.build(Instr::Mul(sizeof, amount.instr())).unwrap();
|
||||||
let instr = scope.block.build(Instr::FunctionCall(function, vec![bytes])).unwrap();
|
let instr = scope.block.build(Instr::FunctionCall(function, vec![bytes])).unwrap();
|
||||||
@ -402,7 +394,7 @@ impl IntrinsicFunction for IntrinsicMalloc {
|
|||||||
pub struct IntrinsicNullPtr(TypeKind);
|
pub struct IntrinsicNullPtr(TypeKind);
|
||||||
impl IntrinsicFunction for IntrinsicNullPtr {
|
impl IntrinsicFunction for IntrinsicNullPtr {
|
||||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
||||||
let zero = scope.block.build(Instr::Constant(ConstValue::I8(0))).unwrap();
|
let zero = scope.block.build(Instr::Constant(ConstValueKind::I8(0))).unwrap();
|
||||||
let instr = scope
|
let instr = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::IntToPtr(
|
.build(Instr::IntToPtr(
|
||||||
|
@ -3,13 +3,14 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
|||||||
use allocator::{Allocator, AllocatorScope};
|
use allocator::{Allocator, AllocatorScope};
|
||||||
use intrinsics::*;
|
use intrinsics::*;
|
||||||
use reid_lib::{
|
use reid_lib::{
|
||||||
|
builder::ConstantValue,
|
||||||
compile::CompiledModule,
|
compile::CompiledModule,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugFileData, DebugLexicalScope, DebugLocalVariable, DebugLocation, DebugMetadata, DebugRecordKind,
|
DebugFileData, DebugLexicalScope, DebugLocalVariable, DebugLocation, DebugMetadata, DebugRecordKind,
|
||||||
DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DwarfFlags,
|
DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DwarfFlags,
|
||||||
InstructionDebugRecordData,
|
InstructionDebugRecordData,
|
||||||
},
|
},
|
||||||
CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, NamedStruct,
|
CmpPredicate, ConstValueKind, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, NamedStruct,
|
||||||
TerminatorKind as Term, Type,
|
TerminatorKind as Term, Type,
|
||||||
};
|
};
|
||||||
use scope::*;
|
use scope::*;
|
||||||
@ -96,6 +97,29 @@ impl Default for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl mir::GlobalKind {
|
||||||
|
fn codegen<'ctx>(
|
||||||
|
&'ctx self,
|
||||||
|
context: &'ctx Context,
|
||||||
|
types: &HashMap<CustomTypeKey, reid_lib::builder::TypeValue>,
|
||||||
|
module: &Module,
|
||||||
|
) -> Result<(ConstantValue, TypeKind), ErrorKind> {
|
||||||
|
Ok(match self {
|
||||||
|
mir::GlobalKind::Literal(literal) => (module.add_constant(literal.as_const_kind()), literal.as_type()),
|
||||||
|
mir::GlobalKind::Array(globals) => {
|
||||||
|
let values = try_all(globals.into_iter().map(|g| g.codegen(context, types, module)).collect())
|
||||||
|
.map_err(|e| e.first().unwrap().clone())?;
|
||||||
|
let elem_ty = values.iter().map(|(_, t)| t.clone()).next().unwrap_or(TypeKind::Void);
|
||||||
|
let values = values.iter().map(|(v, _)| *v).collect::<Vec<_>>();
|
||||||
|
(
|
||||||
|
module.add_constant(ConstValueKind::Array(values, elem_ty.get_type(&types))),
|
||||||
|
TypeKind::Array(Box::new(elem_ty), globals.len() as u64),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl mir::Module {
|
impl mir::Module {
|
||||||
fn codegen<'ctx>(
|
fn codegen<'ctx>(
|
||||||
&'ctx self,
|
&'ctx self,
|
||||||
@ -177,6 +201,12 @@ impl mir::Module {
|
|||||||
insert_debug!(&TypeKind::CustomType(type_key.clone()));
|
insert_debug!(&TypeKind::CustomType(type_key.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut globals = HashMap::new();
|
||||||
|
for global in &self.globals {
|
||||||
|
let (const_value, _) = global.kind.codegen(context, &type_values, &module)?;
|
||||||
|
globals.insert(global.name.clone(), module.add_global(&global.name, const_value));
|
||||||
|
}
|
||||||
|
|
||||||
let mut functions = HashMap::new();
|
let mut functions = HashMap::new();
|
||||||
|
|
||||||
for function in &self.functions {
|
for function in &self.functions {
|
||||||
@ -350,6 +380,7 @@ impl mir::Module {
|
|||||||
functions: &functions,
|
functions: &functions,
|
||||||
types: &types,
|
types: &types,
|
||||||
type_values: &type_values,
|
type_values: &type_values,
|
||||||
|
globals: &globals,
|
||||||
stack_values: HashMap::new(),
|
stack_values: HashMap::new(),
|
||||||
debug: Some(Debug {
|
debug: Some(Debug {
|
||||||
info: &debug,
|
info: &debug,
|
||||||
@ -432,6 +463,7 @@ impl mir::Module {
|
|||||||
scope: compile_unit.clone(),
|
scope: compile_unit.clone(),
|
||||||
types: &debug_types,
|
types: &debug_types,
|
||||||
}),
|
}),
|
||||||
|
globals: &globals,
|
||||||
binops: &binops,
|
binops: &binops,
|
||||||
allocator: Rc::new(RefCell::new(allocator)),
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
};
|
};
|
||||||
@ -492,6 +524,7 @@ impl mir::Module {
|
|||||||
scope: compile_unit.clone(),
|
scope: compile_unit.clone(),
|
||||||
types: &debug_types,
|
types: &debug_types,
|
||||||
}),
|
}),
|
||||||
|
globals: &globals,
|
||||||
binops: &binops,
|
binops: &binops,
|
||||||
allocator: Rc::new(RefCell::new(allocator)),
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
};
|
};
|
||||||
@ -695,6 +728,7 @@ impl mir::Statement {
|
|||||||
mir::StmtKind::Let(NamedVariableRef(ty, name, meta), mutable, expression) => {
|
mir::StmtKind::Let(NamedVariableRef(ty, name, meta), mutable, expression) => {
|
||||||
let value = expression.codegen(scope, &state)?.unwrap();
|
let value = expression.codegen(scope, &state)?.unwrap();
|
||||||
|
|
||||||
|
dbg!(&scope.allocator, &meta, &value.1);
|
||||||
let alloca = scope
|
let alloca = scope
|
||||||
.allocate(meta, &value.1)
|
.allocate(meta, &value.1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -784,7 +818,7 @@ impl mir::Statement {
|
|||||||
let condition_res = condition.codegen(&mut condition_scope, state)?.unwrap();
|
let condition_res = condition.codegen(&mut condition_scope, state)?.unwrap();
|
||||||
let true_instr = condition_scope
|
let true_instr = condition_scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Constant(ConstValue::Bool(true)))
|
.build(Instr::Constant(ConstValueKind::Bool(true)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let check = condition_scope
|
let check = condition_scope
|
||||||
.block
|
.block
|
||||||
@ -1031,7 +1065,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let first = scope
|
let first = scope
|
||||||
.block
|
.block
|
||||||
.build_named("array.zero", Instr::Constant(ConstValue::U32(0)))
|
.build_named("array.zero", Instr::Constant(ConstValueKind::U32(0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(
|
(
|
||||||
scope
|
scope
|
||||||
@ -1098,11 +1132,11 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let index_expr = scope
|
let index_expr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(index.to_string(), Instr::Constant(ConstValue::U32(index as u32)))
|
.build_named(index.to_string(), Instr::Constant(ConstValueKind::U32(index as u32)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let first = scope
|
let first = scope
|
||||||
.block
|
.block
|
||||||
.build_named("zero", Instr::Constant(ConstValue::U32(0)))
|
.build_named("zero", Instr::Constant(ConstValueKind::U32(0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ptr = scope
|
let ptr = scope
|
||||||
.block
|
.block
|
||||||
@ -1322,6 +1356,14 @@ impl mir::Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?,
|
mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?,
|
||||||
|
mir::ExprKind::GlobalRef(global_name, ty) => {
|
||||||
|
let global_value = scope.globals.get(global_name).unwrap();
|
||||||
|
let a = Some(StackValue(
|
||||||
|
StackValueKind::Literal(scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap()),
|
||||||
|
TypeKind::UserPtr(Box::new(ty.clone())),
|
||||||
|
));
|
||||||
|
a
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if let Some(value) = &value {
|
if let Some(value) = &value {
|
||||||
value.instr().maybe_location(&mut scope.block, location.clone());
|
value.instr().maybe_location(&mut scope.block, location.clone());
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
||||||
|
|
||||||
use reid_lib::{
|
use reid_lib::{
|
||||||
builder::{InstructionValue, TypeValue},
|
builder::{GlobalValue, InstructionValue, TypeValue},
|
||||||
debug_information::{DebugInformation, DebugLocation, DebugScopeValue, DebugTypeValue},
|
debug_information::{DebugInformation, DebugLocation, DebugScopeValue, DebugTypeValue},
|
||||||
Block, Context, Function, Instr, Module,
|
Block, Context, Function, Instr, Module,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::intrinsics::MacroFunction,
|
|
||||||
lexer::FullToken,
|
lexer::FullToken,
|
||||||
mir::{
|
mir::{
|
||||||
self,
|
|
||||||
pass::{AssociatedFunctionKey, BinopKey},
|
pass::{AssociatedFunctionKey, BinopKey},
|
||||||
CustomTypeKey, FunctionParam, Metadata, SourceModuleId, TypeDefinition, TypeKind,
|
CustomTypeKey, FunctionParam, Metadata, SourceModuleId, TypeDefinition, TypeKind,
|
||||||
},
|
},
|
||||||
@ -32,6 +30,7 @@ pub struct Scope<'ctx, 'scope> {
|
|||||||
pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>,
|
pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>,
|
||||||
pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>,
|
pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>,
|
||||||
pub(super) stack_values: HashMap<String, StackValue>,
|
pub(super) stack_values: HashMap<String, StackValue>,
|
||||||
|
pub(super) globals: &'scope HashMap<String, GlobalValue>,
|
||||||
pub(super) debug: Option<Debug<'ctx>>,
|
pub(super) debug: Option<Debug<'ctx>>,
|
||||||
pub(super) allocator: Rc<RefCell<Allocator>>,
|
pub(super) allocator: Rc<RefCell<Allocator>>,
|
||||||
}
|
}
|
||||||
@ -53,6 +52,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
stack_values: self.stack_values.clone(),
|
stack_values: self.stack_values.clone(),
|
||||||
debug: self.debug.clone(),
|
debug: self.debug.clone(),
|
||||||
allocator: self.allocator.clone(),
|
allocator: self.allocator.clone(),
|
||||||
|
globals: self.globals,
|
||||||
binops: self.binops,
|
binops: self.binops,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use reid_lib::{
|
|||||||
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocation, DebugPointerType,
|
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocation, DebugPointerType,
|
||||||
DebugPosition, DebugScopeValue, DebugStructType, DebugTypeData, DebugTypeValue, DwarfEncoding, DwarfFlags,
|
DebugPosition, DebugScopeValue, DebugStructType, DebugTypeData, DebugTypeValue, DwarfEncoding, DwarfFlags,
|
||||||
},
|
},
|
||||||
Block, CmpPredicate, ConstValue, Instr, Type,
|
Block, CmpPredicate, ConstValueKind, Instr, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -34,34 +34,36 @@ impl mir::CmpOperator {
|
|||||||
|
|
||||||
impl mir::Literal {
|
impl mir::Literal {
|
||||||
pub(super) fn as_const(&self, block: &mut Block) -> InstructionValue {
|
pub(super) fn as_const(&self, block: &mut Block) -> InstructionValue {
|
||||||
block.build_named(format!("{}", self), self.as_const_kind()).unwrap()
|
block
|
||||||
|
.build_named(format!("{}", self), Instr::Constant(self.as_const_kind()))
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn as_const_kind(&self) -> Instr {
|
pub(super) fn as_const_kind(&self) -> ConstValueKind {
|
||||||
Instr::Constant(match self.clone() {
|
match self.clone() {
|
||||||
mir::Literal::I8(val) => ConstValue::I8(val),
|
mir::Literal::I8(val) => ConstValueKind::I8(val),
|
||||||
mir::Literal::I16(val) => ConstValue::I16(val),
|
mir::Literal::I16(val) => ConstValueKind::I16(val),
|
||||||
mir::Literal::I32(val) => ConstValue::I32(val),
|
mir::Literal::I32(val) => ConstValueKind::I32(val),
|
||||||
mir::Literal::I64(val) => ConstValue::I64(val),
|
mir::Literal::I64(val) => ConstValueKind::I64(val),
|
||||||
mir::Literal::I128(val) => ConstValue::I128(val),
|
mir::Literal::I128(val) => ConstValueKind::I128(val),
|
||||||
mir::Literal::U8(val) => ConstValue::U8(val),
|
mir::Literal::U8(val) => ConstValueKind::U8(val),
|
||||||
mir::Literal::U16(val) => ConstValue::U16(val),
|
mir::Literal::U16(val) => ConstValueKind::U16(val),
|
||||||
mir::Literal::U32(val) => ConstValue::U32(val),
|
mir::Literal::U32(val) => ConstValueKind::U32(val),
|
||||||
mir::Literal::U64(val) => ConstValue::U64(val),
|
mir::Literal::U64(val) => ConstValueKind::U64(val),
|
||||||
mir::Literal::U128(val) => ConstValue::U128(val),
|
mir::Literal::U128(val) => ConstValueKind::U128(val),
|
||||||
mir::Literal::Bool(val) => ConstValue::Bool(val),
|
mir::Literal::Bool(val) => ConstValueKind::Bool(val),
|
||||||
mir::Literal::String(val) => ConstValue::Str(val.clone()),
|
mir::Literal::String(val) => ConstValueKind::Str(val.clone()),
|
||||||
mir::Literal::Vague(VagueLiteral::Number(val)) => ConstValue::I32(val as i32),
|
mir::Literal::Vague(VagueLiteral::Number(val)) => ConstValueKind::I32(val as i32),
|
||||||
mir::Literal::Vague(VagueLiteral::Decimal(val)) => ConstValue::F32(val as f32),
|
mir::Literal::Vague(VagueLiteral::Decimal(val)) => ConstValueKind::F32(val as f32),
|
||||||
mir::Literal::F16(val) => ConstValue::F16(val),
|
mir::Literal::F16(val) => ConstValueKind::F16(val),
|
||||||
mir::Literal::F32B(val) => ConstValue::F32B(val),
|
mir::Literal::F32B(val) => ConstValueKind::F32B(val),
|
||||||
mir::Literal::F32(val) => ConstValue::F32(val),
|
mir::Literal::F32(val) => ConstValueKind::F32(val),
|
||||||
mir::Literal::F64(val) => ConstValue::F64(val),
|
mir::Literal::F64(val) => ConstValueKind::F64(val),
|
||||||
mir::Literal::F80(val) => ConstValue::F80(val),
|
mir::Literal::F80(val) => ConstValueKind::F80(val),
|
||||||
mir::Literal::F128(val) => ConstValue::F128(val),
|
mir::Literal::F128(val) => ConstValueKind::F128(val),
|
||||||
mir::Literal::F128PPC(val) => ConstValue::F128PPC(val),
|
mir::Literal::F128PPC(val) => ConstValueKind::F128PPC(val),
|
||||||
mir::Literal::Char(c) => ConstValue::U8(c as u8),
|
mir::Literal::Char(c) => ConstValueKind::U8(c as u8),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
ast::token_stream::{self, TokenRange},
|
ast::token_stream::{self, TokenRange},
|
||||||
codegen,
|
codegen,
|
||||||
lexer::{self, Cursor, FullToken, Position},
|
lexer::{self, Cursor, FullToken, Position},
|
||||||
mir::{self, pass, typecheck, Metadata, SourceModuleId},
|
mir::{self, macros, pass, typecheck, Metadata, SourceModuleId},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::mir::typecheck::ErrorKind as TypecheckError;
|
use crate::mir::typecheck::ErrorKind as TypecheckError;
|
||||||
@ -33,6 +33,8 @@ pub enum ErrorKind {
|
|||||||
TypeInferenceError(#[source] mir::pass::Error<TypecheckError>),
|
TypeInferenceError(#[source] mir::pass::Error<TypecheckError>),
|
||||||
#[error("{}{}", label("(Linker) "), .0.kind)]
|
#[error("{}{}", label("(Linker) "), .0.kind)]
|
||||||
LinkerError(#[from] mir::pass::Error<mir::linker::ErrorKind>),
|
LinkerError(#[from] mir::pass::Error<mir::linker::ErrorKind>),
|
||||||
|
#[error("{}{}", label("(Macro) "), .0)]
|
||||||
|
MacroError(#[from] mir::pass::Error<macros::ErrorKind>),
|
||||||
#[error("{}{}", label("(Codegen) "), .0)]
|
#[error("{}{}", label("(Codegen) "), .0)]
|
||||||
CodegenError(#[from] codegen::ErrorKind),
|
CodegenError(#[from] codegen::ErrorKind),
|
||||||
}
|
}
|
||||||
@ -58,6 +60,7 @@ impl ErrorKind {
|
|||||||
ErrorKind::CodegenError(error) => match error {
|
ErrorKind::CodegenError(error) => match error {
|
||||||
codegen::ErrorKind::Null => Default::default(),
|
codegen::ErrorKind::Null => Default::default(),
|
||||||
},
|
},
|
||||||
|
ErrorKind::MacroError(error) => error.metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,10 @@ use mir::{
|
|||||||
};
|
};
|
||||||
use reid_lib::{compile::CompileOutput, Context};
|
use reid_lib::{compile::CompileOutput, Context};
|
||||||
|
|
||||||
use crate::ast::TopLevelStatement;
|
use crate::{
|
||||||
|
ast::TopLevelStatement,
|
||||||
|
mir::macros::{form_macros, MacroPass},
|
||||||
|
};
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod codegen;
|
mod codegen;
|
||||||
@ -133,6 +136,12 @@ pub fn perform_all_passes<'map>(
|
|||||||
is_lib: true,
|
is_lib: true,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
for module in &mut context.modules {
|
||||||
|
for intrinsic in form_intrinsics() {
|
||||||
|
module.1.functions.insert(0, intrinsic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
println!("{:-^100}", "LINKER OUTPUT");
|
println!("{:-^100}", "LINKER OUTPUT");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@ -140,6 +149,29 @@ pub fn perform_all_passes<'map>(
|
|||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&state);
|
dbg!(&state);
|
||||||
|
|
||||||
|
if !state.errors.is_empty() {
|
||||||
|
return Err(ReidError::from_kind(
|
||||||
|
state.errors.iter().map(|e| e.clone().into()).collect(),
|
||||||
|
module_map.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = context.pass(&mut MacroPass { macros: form_macros() })?;
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("{:-^100}", "MACRO OUTPUT");
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("{:#}", &context);
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
dbg!(&state);
|
||||||
|
|
||||||
|
if !state.errors.is_empty() {
|
||||||
|
return Err(ReidError::from_kind(
|
||||||
|
state.errors.iter().map(|e| e.clone().into()).collect(),
|
||||||
|
module_map.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let mut binops = BinopMap::default();
|
let mut binops = BinopMap::default();
|
||||||
for module in &mut context.modules {
|
for module in &mut context.modules {
|
||||||
for intrinsic in form_intrinsic_binops() {
|
for intrinsic in form_intrinsic_binops() {
|
||||||
@ -160,19 +192,6 @@ pub fn perform_all_passes<'map>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for module in &mut context.modules {
|
|
||||||
for intrinsic in form_intrinsics() {
|
|
||||||
module.1.functions.insert(0, intrinsic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !state.errors.is_empty() {
|
|
||||||
return Err(ReidError::from_kind(
|
|
||||||
state.errors.iter().map(|e| e.clone().into()).collect(),
|
|
||||||
module_map.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut refs = TypeRefs::with_binops(binops);
|
let mut refs = TypeRefs::with_binops(binops);
|
||||||
|
|
||||||
let state = context.pass(&mut TypeInference { refs: &mut refs })?;
|
let state = context.pass(&mut TypeInference { refs: &mut refs })?;
|
||||||
|
@ -280,6 +280,7 @@ impl Display for ExprKind {
|
|||||||
write!(f, "::")?;
|
write!(f, "::")?;
|
||||||
Display::fmt(function_call, f)
|
Display::fmt(function_call, f)
|
||||||
}
|
}
|
||||||
|
ExprKind::GlobalRef(global_value, type_kind) => write!(f, "todo globals"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,6 +429,7 @@ impl Expression {
|
|||||||
Err(_) => Ok((ReturnKind::Soft, type_kind.clone())),
|
Err(_) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||||
},
|
},
|
||||||
AssociatedFunctionCall(_, fcall) => fcall.return_type(),
|
AssociatedFunctionCall(_, fcall) => fcall.return_type(),
|
||||||
|
GlobalRef(_, type_kind) => Ok((ReturnKind::Soft, TypeKind::UserPtr(Box::new(type_kind.clone())))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +449,7 @@ impl Expression {
|
|||||||
ExprKind::If(_) => None,
|
ExprKind::If(_) => None,
|
||||||
ExprKind::CastTo(expression, _) => expression.backing_var(),
|
ExprKind::CastTo(expression, _) => expression.backing_var(),
|
||||||
ExprKind::AssociatedFunctionCall(..) => None,
|
ExprKind::AssociatedFunctionCall(..) => None,
|
||||||
|
ExprKind::GlobalRef(..) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,6 +495,7 @@ impl Expression {
|
|||||||
ExprKind::Deref(_) => None,
|
ExprKind::Deref(_) => None,
|
||||||
ExprKind::CastTo(expression, _) => expression.num_value()?,
|
ExprKind::CastTo(expression, _) => expression.num_value()?,
|
||||||
ExprKind::AssociatedFunctionCall(..) => None,
|
ExprKind::AssociatedFunctionCall(..) => None,
|
||||||
|
ExprKind::GlobalRef(..) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,33 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::codegen::intrinsics::MacroFunction;
|
use crate::mir::{self, FunctionCall, GlobalKind, GlobalValue, IfExpression, Literal, TypeKind, WhileStatement};
|
||||||
|
|
||||||
use super::pass::{Pass, PassResult, PassState};
|
use super::pass::{Pass, PassResult, PassState};
|
||||||
|
|
||||||
|
pub trait MacroFunction: std::fmt::Debug {
|
||||||
|
fn generate<'ctx, 'a>(&self, params: &[mir::Literal]) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
#[error("Should never be encountered!")]
|
#[error("Should never be encountered!")]
|
||||||
Null,
|
Null,
|
||||||
|
#[error("No such macro {0} defined")]
|
||||||
|
NoSuchMacro(String),
|
||||||
|
#[error("Macro arguments may only be literals")]
|
||||||
|
InvalidMacroArgs,
|
||||||
|
#[error("Got {0} parameters, expected {1}")]
|
||||||
|
InvalidAmountOfParams(u32, u32),
|
||||||
|
#[error("Expected argument type of {0}, got {1}")]
|
||||||
|
InvalidArgumentType(TypeKind, TypeKind),
|
||||||
|
#[error("Error executing macro: {0}")]
|
||||||
|
MacroExecutionError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Struct used to implement a type-checking pass that can be performed on the
|
/// Struct used to implement a type-checking pass that can be performed on the
|
||||||
/// MIR.
|
/// MIR.
|
||||||
pub struct MacroPass {
|
pub struct MacroPass {
|
||||||
macros: HashMap<String, Box<dyn MacroFunction>>,
|
pub(crate) macros: HashMap<String, Box<dyn MacroFunction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type MacroPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>;
|
type MacroPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>;
|
||||||
@ -22,7 +36,193 @@ impl Pass for MacroPass {
|
|||||||
type Data = ();
|
type Data = ();
|
||||||
type TError = ErrorKind;
|
type TError = ErrorKind;
|
||||||
|
|
||||||
fn expr(&mut self, expr: &mut super::Expression, state: MacroPassState) -> PassResult {
|
fn context(&mut self, _context: &mut mir::Context, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module(&mut self, module: &mut mir::Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||||
|
for function in &mut module.functions {
|
||||||
|
let globals = match &mut function.kind {
|
||||||
|
mir::FunctionDefinitionKind::Local(block, _) => block.gen_macros(self, &mut state),
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
module.globals.extend(globals);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl mir::Block {
|
||||||
|
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||||
|
let mut globals = Vec::new();
|
||||||
|
for statement in &mut self.statements {
|
||||||
|
globals.extend(statement.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
if let Some((_, Some(return_expr))) = &mut self.return_expression {
|
||||||
|
globals.extend(return_expr.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
globals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mir::Statement {
|
||||||
|
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||||
|
let mut globals = Vec::new();
|
||||||
|
match &mut self.0 {
|
||||||
|
mir::StmtKind::Let(.., expr) => {
|
||||||
|
globals.extend(expr.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::StmtKind::Set(lhs, rhs) => {
|
||||||
|
globals.extend(lhs.gen_macros(data, state));
|
||||||
|
globals.extend(rhs.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::StmtKind::Import(_) => {}
|
||||||
|
mir::StmtKind::Expression(expr) => {
|
||||||
|
globals.extend(expr.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
|
||||||
|
globals.extend(condition.gen_macros(data, state));
|
||||||
|
globals.extend(block.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
globals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mir::Expression {
|
||||||
|
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||||
|
let mut globals = Vec::new();
|
||||||
|
match &mut self.0 {
|
||||||
|
mir::ExprKind::FunctionCall(function_call) => {
|
||||||
|
if function_call.is_macro {
|
||||||
|
if let Some(existing_macro) = data.macros.get(&function_call.name) {
|
||||||
|
let mut literals = Vec::new();
|
||||||
|
for param in &function_call.parameters {
|
||||||
|
match ¶m.0 {
|
||||||
|
super::ExprKind::Literal(literal) => literals.push(literal.clone()),
|
||||||
|
_ => state.note_errors(&vec![ErrorKind::InvalidMacroArgs], param.1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (generated_globals, expr) = state.or_else(
|
||||||
|
existing_macro
|
||||||
|
.generate(&literals)
|
||||||
|
.map(|(globals, kind)| (globals, mir::Expression(kind, self.1))),
|
||||||
|
(Vec::new(), self.clone()),
|
||||||
|
self.1,
|
||||||
|
);
|
||||||
|
globals.extend(generated_globals);
|
||||||
|
*self = expr;
|
||||||
|
} else {
|
||||||
|
state.note_errors(
|
||||||
|
&vec![ErrorKind::NoSuchMacro(function_call.name.clone())],
|
||||||
|
function_call.meta,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::ExprKind::Variable(_) => {}
|
||||||
|
mir::ExprKind::Indexed(expression, _, expression1) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
globals.extend(expression1.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::Accessed(expression, ..) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::Array(expressions) => {
|
||||||
|
for expression in expressions {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::ExprKind::Struct(_, items) => {
|
||||||
|
for item in items {
|
||||||
|
globals.extend(item.1.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::ExprKind::Literal(_) => {}
|
||||||
|
mir::ExprKind::BinOp(_, expression, expression1, _) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
globals.extend(expression1.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::AssociatedFunctionCall(
|
||||||
|
_,
|
||||||
|
FunctionCall {
|
||||||
|
parameters, is_macro, ..
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
for expression in parameters {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||||
|
globals.extend(cond.gen_macros(data, state));
|
||||||
|
globals.extend(lhs.gen_macros(data, state));
|
||||||
|
if let Some(rhs) = rhs.as_mut() {
|
||||||
|
globals.extend(rhs.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::ExprKind::Block(block) => {
|
||||||
|
globals.extend(block.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::Borrow(expression, _) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::Deref(expression) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::CastTo(expression, _) => {
|
||||||
|
globals.extend(expression.gen_macros(data, state));
|
||||||
|
}
|
||||||
|
mir::ExprKind::GlobalRef(..) => {}
|
||||||
|
}
|
||||||
|
globals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn form_macros() -> HashMap<String, Box<dyn MacroFunction>> {
|
||||||
|
let mut macros: HashMap<String, Box<dyn MacroFunction>> = HashMap::new();
|
||||||
|
|
||||||
|
macros.insert("test_macro".to_owned(), Box::new(TestMacro));
|
||||||
|
|
||||||
|
macros
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TestMacro;
|
||||||
|
impl MacroFunction for TestMacro {
|
||||||
|
fn generate<'ctx, 'a>(&self, literals: &[mir::Literal]) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind> {
|
||||||
|
if literals.len() != 1 {
|
||||||
|
return Err(ErrorKind::InvalidAmountOfParams(literals.len() as u32, 1));
|
||||||
|
}
|
||||||
|
let literal = literals.get(0).unwrap();
|
||||||
|
let Literal::String(path) = literal else {
|
||||||
|
return Err(ErrorKind::InvalidArgumentType(
|
||||||
|
literal.as_type(),
|
||||||
|
TypeKind::UserPtr(Box::new(TypeKind::Char)),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let contents = match std::fs::read(path) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(e) => return Err(ErrorKind::MacroExecutionError(format!("{}", e))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let literals = contents
|
||||||
|
.iter()
|
||||||
|
.map(|c| GlobalKind::Literal(Literal::U8(*c)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let len = literals.len();
|
||||||
|
|
||||||
|
let global_name = "sometestglobalvalue".to_owned();
|
||||||
|
let global = GlobalValue {
|
||||||
|
name: global_name.clone(),
|
||||||
|
kind: GlobalKind::Array(literals),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
vec![global.clone()],
|
||||||
|
mir::ExprKind::GlobalRef(global_name, TypeKind::U8),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::{collections::HashMap, path::PathBuf};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::token_stream::TokenRange,
|
ast::token_stream::TokenRange,
|
||||||
codegen::intrinsics::{IntrinsicFunction, MacroFunction},
|
codegen::intrinsics::IntrinsicFunction,
|
||||||
lexer::{FullToken, Position},
|
lexer::{FullToken, Position},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -271,6 +271,7 @@ pub enum ExprKind {
|
|||||||
Borrow(Box<Expression>, bool),
|
Borrow(Box<Expression>, bool),
|
||||||
Deref(Box<Expression>),
|
Deref(Box<Expression>),
|
||||||
CastTo(Box<Expression>, TypeKind),
|
CastTo(Box<Expression>, TypeKind),
|
||||||
|
GlobalRef(String, TypeKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -421,11 +422,24 @@ pub struct Module {
|
|||||||
pub functions: Vec<FunctionDefinition>,
|
pub functions: Vec<FunctionDefinition>,
|
||||||
pub typedefs: Vec<TypeDefinition>,
|
pub typedefs: Vec<TypeDefinition>,
|
||||||
pub binop_defs: Vec<BinopDefinition>,
|
pub binop_defs: Vec<BinopDefinition>,
|
||||||
|
pub globals: Vec<GlobalValue>,
|
||||||
pub path: Option<PathBuf>,
|
pub path: Option<PathBuf>,
|
||||||
pub tokens: Vec<FullToken>,
|
pub tokens: Vec<FullToken>,
|
||||||
pub is_main: bool,
|
pub is_main: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct GlobalValue {
|
||||||
|
pub name: String,
|
||||||
|
pub kind: GlobalKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum GlobalKind {
|
||||||
|
Literal(Literal),
|
||||||
|
Array(Vec<GlobalKind>),
|
||||||
|
}
|
||||||
|
|
||||||
pub type ModuleMap = HashMap<SourceModuleId, Module>;
|
pub type ModuleMap = HashMap<SourceModuleId, Module>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -503,6 +503,10 @@ impl Block {
|
|||||||
statement.pass(pass, state, &mut scope, mod_id)?;
|
statement.pass(pass, state, &mut scope, mod_id)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some((_, Some(return_expr))) = &mut self.return_expression {
|
||||||
|
return_expr.pass(pass, state, &mut scope, mod_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
pass.block(self, PassState::from(state, &mut scope, Some(mod_id)))
|
pass.block(self, PassState::from(state, &mut scope, Some(mod_id)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,6 +615,7 @@ impl Expression {
|
|||||||
ExprKind::Borrow(expression, _) => expression.pass(pass, state, scope, mod_id)?,
|
ExprKind::Borrow(expression, _) => expression.pass(pass, state, scope, mod_id)?,
|
||||||
ExprKind::Deref(expression) => expression.pass(pass, state, scope, mod_id)?,
|
ExprKind::Deref(expression) => expression.pass(pass, state, scope, mod_id)?,
|
||||||
ExprKind::CastTo(expression, _) => expression.pass(pass, state, scope, mod_id)?,
|
ExprKind::CastTo(expression, _) => expression.pass(pass, state, scope, mod_id)?,
|
||||||
|
ExprKind::GlobalRef(..) => {}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -767,6 +767,10 @@ impl Expression {
|
|||||||
Ok(function_call.return_type.clone().resolve_ref(typerefs))
|
Ok(function_call.return_type.clone().resolve_ref(typerefs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExprKind::GlobalRef(global_value, type_kind) => Ok(self
|
||||||
|
.return_type(typerefs, state.scope.module_id.unwrap())
|
||||||
|
.map(|r| r.1)
|
||||||
|
.unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,6 +660,10 @@ impl Expression {
|
|||||||
// Provide function return type
|
// Provide function return type
|
||||||
Ok(type_refs.from_type(&fn_call.ret).unwrap())
|
Ok(type_refs.from_type(&fn_call.ret).unwrap())
|
||||||
}
|
}
|
||||||
|
ExprKind::GlobalRef(global_value, type_kind) => Ok(self
|
||||||
|
.return_type(type_refs.types, state.scope.module_id.unwrap())
|
||||||
|
.map(|r| type_refs.from_type(&r.1).unwrap())
|
||||||
|
.unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user