Add possibility to call instructions and store functions in values
This commit is contained in:
parent
100cd96a6d
commit
17545baa50
@ -4,10 +4,11 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData,
|
||||
ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
||||
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData,
|
||||
Instr, InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
||||
debug_information::{
|
||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData,
|
||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue,
|
||||
InstructionDebugRecordData,
|
||||
},
|
||||
util::match_types,
|
||||
};
|
||||
@ -114,7 +115,11 @@ impl Builder {
|
||||
value
|
||||
}
|
||||
|
||||
pub(crate) fn set_debug_information(&self, mod_val: &ModuleValue, debug_info: DebugInformation) {
|
||||
pub(crate) fn set_debug_information(
|
||||
&self,
|
||||
mod_val: &ModuleValue,
|
||||
debug_info: DebugInformation,
|
||||
) {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(mod_val.0);
|
||||
@ -132,7 +137,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn add_function(&self, mod_val: &ModuleValue, data: FunctionData) -> FunctionValue {
|
||||
pub(crate) unsafe fn add_function(
|
||||
&self,
|
||||
mod_val: &ModuleValue,
|
||||
data: FunctionData,
|
||||
) -> FunctionValue {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(mod_val.0);
|
||||
@ -190,7 +199,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn build_constant(&self, module: ModuleValue, kind: ConstValueKind) -> ConstantValue {
|
||||
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);
|
||||
@ -219,15 +232,27 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(module.0);
|
||||
module.functions.iter().find(|f| f.data.name == *name).map(|f| f.value)
|
||||
module
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.data.name == *name)
|
||||
.map(|f| f.value)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) {
|
||||
pub(crate) unsafe fn add_instruction_location(
|
||||
&self,
|
||||
value: &InstructionValue,
|
||||
location: DebugLocationValue,
|
||||
) {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
||||
@ -238,7 +263,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn add_instruction_metadata(&self, value: &InstructionValue, metadata: DebugMetadataValue) {
|
||||
pub(crate) unsafe fn add_instruction_metadata(
|
||||
&self,
|
||||
value: &InstructionValue,
|
||||
metadata: DebugMetadataValue,
|
||||
) {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
||||
@ -249,7 +278,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn add_instruction_record(&self, value: &InstructionValue, record: InstructionDebugRecordData) {
|
||||
pub(crate) unsafe fn add_instruction_record(
|
||||
&self,
|
||||
value: &InstructionValue,
|
||||
record: InstructionDebugRecordData,
|
||||
) {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
||||
@ -260,7 +293,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn set_debug_subprogram(&self, value: &FunctionValue, subprogram: DebugScopeValue) {
|
||||
pub(crate) unsafe fn set_debug_subprogram(
|
||||
&self,
|
||||
value: &FunctionValue,
|
||||
subprogram: DebugScopeValue,
|
||||
) {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(value.0.0);
|
||||
@ -269,7 +306,11 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn terminate(&self, block: &BlockValue, value: TerminatorKind) -> CompileResult<()> {
|
||||
pub(crate) unsafe fn terminate(
|
||||
&self,
|
||||
block: &BlockValue,
|
||||
value: TerminatorKind,
|
||||
) -> CompileResult<()> {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
let module = modules.get_unchecked_mut(block.0.0.0);
|
||||
@ -551,7 +592,10 @@ impl Builder {
|
||||
}
|
||||
for (a, b) in param_types.iter().zip(params) {
|
||||
if *a != b.get_type(&self)? {
|
||||
return Err(ErrorKind::TypesIncompatible(a.clone(), b.get_type(&self)?));
|
||||
return Err(ErrorKind::TypesIncompatible(
|
||||
a.clone(),
|
||||
b.get_type(&self)?,
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -662,6 +706,14 @@ impl Builder {
|
||||
Err(ErrorKind::NotPointer(val, val_ty))
|
||||
}
|
||||
}
|
||||
Instr::Function(_) => Ok(()),
|
||||
Instr::DynFunctionCall(instr, _) => {
|
||||
let fn_ty = instr.get_type(&self)?;
|
||||
let Type::Function(..) = fn_ty else {
|
||||
return Err(ErrorKind::NotPointer(instr, fn_ty));
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -709,7 +761,11 @@ impl InstructionValue {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn maybe_location(self, block: &mut Block, location: Option<DebugLocationValue>) -> InstructionValue {
|
||||
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);
|
||||
@ -822,6 +878,17 @@ impl InstructionValue {
|
||||
Ok(kind.get_type())
|
||||
}
|
||||
IsNull(_) => Ok(Type::Bool),
|
||||
Function(fun) => {
|
||||
let data = builder.function_data(fun);
|
||||
Ok(Type::Function(data.params, Box::new(data.ret)))
|
||||
}
|
||||
DynFunctionCall(instr, _) => {
|
||||
let fn_ty = instr.get_type(builder)?;
|
||||
let Type::Function(_, ret_ty) = fn_ty else {
|
||||
panic!()
|
||||
};
|
||||
Ok(*ret_ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
190
src/compile.rs
190
src/compile.rs
@ -20,8 +20,8 @@ use llvm_sys::{
|
||||
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
|
||||
},
|
||||
target_machine::{
|
||||
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple,
|
||||
LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
|
||||
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
|
||||
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
|
||||
},
|
||||
};
|
||||
|
||||
@ -35,8 +35,8 @@ use crate::{
|
||||
use super::{
|
||||
CmpPredicate, ConstValueKind, Context, TerminatorKind, Type,
|
||||
builder::{
|
||||
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue,
|
||||
ModuleHolder,
|
||||
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder,
|
||||
InstructionValue, ModuleHolder,
|
||||
},
|
||||
};
|
||||
|
||||
@ -120,8 +120,8 @@ impl CompiledModule {
|
||||
);
|
||||
err.into_result().unwrap();
|
||||
|
||||
let llvm_ir =
|
||||
from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string");
|
||||
let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref))
|
||||
.expect("Unable to print LLVM IR to string");
|
||||
|
||||
let mut err = ErrorMessageHolder::null();
|
||||
LLVMVerifyModule(
|
||||
@ -231,8 +231,10 @@ pub struct LLVMValue {
|
||||
impl ModuleHolder {
|
||||
fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef {
|
||||
unsafe {
|
||||
let module_ref =
|
||||
LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref);
|
||||
let module_ref = LLVMModuleCreateWithNameInContext(
|
||||
into_cstring(&self.data.name).as_ptr(),
|
||||
context.context_ref,
|
||||
);
|
||||
|
||||
// Compile the contents
|
||||
|
||||
@ -327,9 +329,12 @@ impl ModuleHolder {
|
||||
constant.value,
|
||||
LLVMValue {
|
||||
ty: constant.kind.get_type(),
|
||||
value_ref: constant
|
||||
.kind
|
||||
.as_llvm(context.context_ref, context.builder_ref, &constants, &types),
|
||||
value_ref: constant.kind.as_llvm(
|
||||
context.context_ref,
|
||||
context.builder_ref,
|
||||
&constants,
|
||||
&types,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -357,7 +362,12 @@ impl ModuleHolder {
|
||||
scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i));
|
||||
}
|
||||
for scope in &scope.inner_scopes {
|
||||
scope.compile_scope(func.metadata.unwrap(), debug.file_ref, debug.scopes, debug.builder);
|
||||
scope.compile_scope(
|
||||
func.metadata.unwrap(),
|
||||
debug.file_ref,
|
||||
debug.scopes,
|
||||
debug.builder,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -402,7 +412,11 @@ impl ModuleHolder {
|
||||
}
|
||||
|
||||
impl DebugLocationHolder {
|
||||
unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
|
||||
unsafe fn compile(
|
||||
&self,
|
||||
context: &LLVMContext,
|
||||
debug: &LLVMDebugInformation,
|
||||
) -> LLVMMetadataRef {
|
||||
unsafe {
|
||||
LLVMDIBuilderCreateDebugLocation(
|
||||
context.context_ref,
|
||||
@ -515,7 +529,8 @@ impl DebugTypeHolder {
|
||||
ptr.name.len(),
|
||||
),
|
||||
DebugTypeData::Array(array) => {
|
||||
let subrange = LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64);
|
||||
let subrange =
|
||||
LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64);
|
||||
let mut elements = vec![subrange];
|
||||
LLVMDIBuilderCreateArrayType(
|
||||
debug.builder,
|
||||
@ -577,7 +592,11 @@ impl DwarfFlags {
|
||||
}
|
||||
|
||||
impl TypeHolder {
|
||||
unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef {
|
||||
unsafe fn compile_type(
|
||||
&self,
|
||||
context: &LLVMContext,
|
||||
types: &HashMap<TypeValue, LLVMTypeRef>,
|
||||
) -> LLVMTypeRef {
|
||||
unsafe {
|
||||
match &self.data.kind {
|
||||
CustomTypeKind::NamedStruct(named_struct) => {
|
||||
@ -585,9 +604,16 @@ impl TypeHolder {
|
||||
for ty in &named_struct.1 {
|
||||
elem_types.push(ty.as_llvm(context.context_ref, types));
|
||||
}
|
||||
let struct_ty =
|
||||
LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr());
|
||||
LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0);
|
||||
let struct_ty = LLVMStructCreateNamed(
|
||||
context.context_ref,
|
||||
into_cstring(named_struct.0.clone()).as_ptr(),
|
||||
);
|
||||
LLVMStructSetBody(
|
||||
struct_ty,
|
||||
elem_types.as_mut_ptr(),
|
||||
elem_types.len() as u32,
|
||||
0,
|
||||
);
|
||||
struct_ty
|
||||
}
|
||||
}
|
||||
@ -617,7 +643,13 @@ impl FunctionHolder {
|
||||
let name = if self.data.flags.is_main {
|
||||
c"main"
|
||||
} else {
|
||||
&into_cstring(&self.data.linkage_name.clone().unwrap_or(self.data.name.clone()))
|
||||
&into_cstring(
|
||||
&self
|
||||
.data
|
||||
.linkage_name
|
||||
.clone()
|
||||
.unwrap_or(self.data.name.clone()),
|
||||
)
|
||||
};
|
||||
|
||||
let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0);
|
||||
@ -625,7 +657,11 @@ impl FunctionHolder {
|
||||
let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type);
|
||||
|
||||
if self.data.flags.inline {
|
||||
let attribute = LLVMCreateEnumAttribute(context.context_ref, LLVMEnumAttribute::AlwaysInline as u32, 0);
|
||||
let attribute = LLVMCreateEnumAttribute(
|
||||
context.context_ref,
|
||||
LLVMEnumAttribute::AlwaysInline as u32,
|
||||
0,
|
||||
);
|
||||
LLVMAddAttributeAtIndex(function_ref, 0, attribute);
|
||||
}
|
||||
|
||||
@ -688,7 +724,10 @@ impl FunctionHolder {
|
||||
|
||||
if self.data.flags.is_imported {
|
||||
if self.data.flags.is_extern {
|
||||
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage);
|
||||
LLVMSetLinkage(
|
||||
own_function.value_ref,
|
||||
LLVMLinkage::LLVMAvailableExternallyLinkage,
|
||||
);
|
||||
} else {
|
||||
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
|
||||
}
|
||||
@ -705,8 +744,10 @@ impl FunctionHolder {
|
||||
continue;
|
||||
}
|
||||
|
||||
let block_ref =
|
||||
LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr());
|
||||
let block_ref = LLVMCreateBasicBlockInContext(
|
||||
module.context_ref,
|
||||
into_cstring(&block.data.name).as_ptr(),
|
||||
);
|
||||
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
|
||||
module.blocks.insert(block.value, block_ref);
|
||||
}
|
||||
@ -738,13 +779,22 @@ impl BlockHolder {
|
||||
.data
|
||||
.terminator
|
||||
.clone()
|
||||
.expect(&format!("Block {} does not have a terminator!", self.data.name))
|
||||
.expect(&format!(
|
||||
"Block {} does not have a terminator!",
|
||||
self.data.name
|
||||
))
|
||||
.compile(module, function, block_ref);
|
||||
|
||||
if let Some(location) = &self.data.terminator_location {
|
||||
LLVMInstructionSetDebugLoc(
|
||||
term_instr.value_ref,
|
||||
*module.debug.as_ref().unwrap().locations.get(&location).unwrap(),
|
||||
*module
|
||||
.debug
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.locations
|
||||
.get(&location)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -752,14 +802,24 @@ impl BlockHolder {
|
||||
}
|
||||
|
||||
impl InstructionHolder {
|
||||
unsafe fn compile(&self, module: &LLVMModule, function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue {
|
||||
unsafe fn compile(
|
||||
&self,
|
||||
module: &LLVMModule,
|
||||
function: &LLVMFunction,
|
||||
_block: LLVMBasicBlockRef,
|
||||
) -> LLVMValue {
|
||||
let _ty = self.value.get_type(module.builder).unwrap();
|
||||
let name = into_cstring(self.name.clone());
|
||||
let val = unsafe {
|
||||
use super::Instr::*;
|
||||
match &self.data.kind {
|
||||
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32),
|
||||
Constant(val) => val.as_llvm(module.context_ref, module.builder_ref, &module.constants, &module.types),
|
||||
Constant(val) => val.as_llvm(
|
||||
module.context_ref,
|
||||
module.builder_ref,
|
||||
&module.constants,
|
||||
&module.types,
|
||||
),
|
||||
Add(lhs, rhs) => {
|
||||
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
|
||||
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
|
||||
@ -1055,6 +1115,34 @@ impl InstructionHolder {
|
||||
let val = module.values.get(&*instruction_value).unwrap().value_ref;
|
||||
LLVMBuildIsNull(module.builder_ref, val, name.as_ptr())
|
||||
}
|
||||
Function(function_value) => module.functions.get(function_value).unwrap().value_ref,
|
||||
DynFunctionCall(function_value, instruction_values) => {
|
||||
let fun = module.values.get(&*function_value).unwrap();
|
||||
let ret_ty =
|
||||
LLVMGetReturnType(fun.ty.as_llvm(module.context_ref, &module.types));
|
||||
|
||||
let mut param_list: Vec<LLVMValueRef> = instruction_values
|
||||
.iter()
|
||||
.map(|i| module.values.get(i).unwrap().value_ref)
|
||||
.collect();
|
||||
|
||||
let is_void = Type::Void.as_llvm(module.context_ref, &module.types) == ret_ty;
|
||||
if is_void {
|
||||
LLVMContextSetDiscardValueNames(module.context_ref, 1);
|
||||
}
|
||||
let value = LLVMBuildCall2(
|
||||
module.builder_ref,
|
||||
fun.ty.as_llvm(module.context_ref, &module.types),
|
||||
fun.value_ref,
|
||||
param_list.as_mut_ptr(),
|
||||
param_list.len() as u32,
|
||||
name.as_ptr(),
|
||||
);
|
||||
if is_void {
|
||||
LLVMContextSetDiscardValueNames(module.context_ref, 0);
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
};
|
||||
if let Some(record) = &self.record {
|
||||
@ -1062,7 +1150,8 @@ impl InstructionHolder {
|
||||
|
||||
unsafe {
|
||||
let mut addr = Vec::<u64>::new();
|
||||
let expr = LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len());
|
||||
let expr =
|
||||
LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len());
|
||||
|
||||
let location = LLVMDIBuilderCreateDebugLocation(
|
||||
module.context_ref,
|
||||
@ -1073,22 +1162,26 @@ impl InstructionHolder {
|
||||
);
|
||||
|
||||
match record.kind {
|
||||
DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore(
|
||||
DebugRecordKind::Declare(instruction_value) => {
|
||||
LLVMDIBuilderInsertDeclareRecordBefore(
|
||||
debug.builder,
|
||||
module.values.get(&instruction_value).unwrap().value_ref,
|
||||
*debug.metadata.get(&record.variable).unwrap(),
|
||||
expr,
|
||||
location,
|
||||
val,
|
||||
),
|
||||
DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore(
|
||||
)
|
||||
}
|
||||
DebugRecordKind::Value(instruction_value) => {
|
||||
LLVMDIBuilderInsertDbgValueRecordBefore(
|
||||
debug.builder,
|
||||
module.values.get(&instruction_value).unwrap().value_ref,
|
||||
*debug.metadata.get(&record.variable).unwrap(),
|
||||
expr,
|
||||
location,
|
||||
val,
|
||||
),
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1101,7 +1194,13 @@ impl InstructionHolder {
|
||||
| LLVMValueKind::LLVMMemoryPhiValueKind => {
|
||||
LLVMInstructionSetDebugLoc(
|
||||
val,
|
||||
*module.debug.as_ref().unwrap().locations.get(&location).unwrap(),
|
||||
*module
|
||||
.debug
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.locations
|
||||
.get(&location)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
@ -1116,7 +1215,12 @@ impl InstructionHolder {
|
||||
}
|
||||
|
||||
impl TerminatorKind {
|
||||
fn compile(&self, module: &LLVMModule, _function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue {
|
||||
fn compile(
|
||||
&self,
|
||||
module: &LLVMModule,
|
||||
_function: &LLVMFunction,
|
||||
_block: LLVMBasicBlockRef,
|
||||
) -> LLVMValue {
|
||||
let _ty = self.get_type(module.builder).unwrap();
|
||||
let val = unsafe {
|
||||
match self {
|
||||
@ -1226,7 +1330,11 @@ impl ConstValueKind {
|
||||
}
|
||||
|
||||
impl Type {
|
||||
fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef {
|
||||
fn as_llvm(
|
||||
&self,
|
||||
context: LLVMContextRef,
|
||||
typemap: &HashMap<TypeValue, LLVMTypeRef>,
|
||||
) -> LLVMTypeRef {
|
||||
use Type::*;
|
||||
unsafe {
|
||||
match self {
|
||||
@ -1247,6 +1355,18 @@ impl Type {
|
||||
F80 => LLVMX86FP80TypeInContext(context),
|
||||
F128 => LLVMFP128TypeInContext(context),
|
||||
F128PPC => LLVMPPCFP128TypeInContext(context),
|
||||
Function(params, ret) => {
|
||||
let mut params_llvm = params
|
||||
.iter()
|
||||
.map(|v| v.as_llvm(context, typemap))
|
||||
.collect::<Vec<_>>();
|
||||
LLVMFunctionType(
|
||||
ret.as_llvm(context, typemap),
|
||||
params_llvm.as_mut_ptr(),
|
||||
params_llvm.len() as u32,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
src/fmt.rs
53
src/fmt.rs
@ -9,10 +9,10 @@ use crate::{
|
||||
CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
|
||||
builder::*,
|
||||
debug_information::{
|
||||
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
|
||||
DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition,
|
||||
DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder,
|
||||
DebugTypeValue,
|
||||
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable,
|
||||
DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable,
|
||||
DebugPointerType, DebugPosition, DebugRecordKind, DebugScopeValue, DebugStructType,
|
||||
DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue,
|
||||
},
|
||||
pad_adapter::PadAdapter,
|
||||
};
|
||||
@ -68,7 +68,11 @@ impl FunctionHolder {
|
||||
.map(|p| format!("{:?}", p))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?;
|
||||
write!(
|
||||
f,
|
||||
"fn {}({}) -> {:?} ",
|
||||
self.data.name, params, self.data.ret
|
||||
)?;
|
||||
|
||||
writeln!(f, "{{")?;
|
||||
let mut state = Default::default();
|
||||
@ -112,7 +116,11 @@ impl BlockHolder {
|
||||
terminator.builder_fmt(&mut inner, builder, debug)?;
|
||||
}
|
||||
if let Some(location) = &self.data.terminator_location {
|
||||
writeln!(inner, " ^ (At {}) ", debug.as_ref().unwrap().get_location(location))?;
|
||||
writeln!(
|
||||
inner,
|
||||
" ^ (At {}) ",
|
||||
debug.as_ref().unwrap().get_location(location)
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -140,7 +148,11 @@ impl InstructionHolder {
|
||||
writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?;
|
||||
}
|
||||
}
|
||||
writeln!(f, "{:?} ({}) = {:?} ", self.value, self.name, self.data.kind)?;
|
||||
writeln!(
|
||||
f,
|
||||
"{:?} ({}) = {:?} ",
|
||||
self.value, self.name, self.data.kind
|
||||
)?;
|
||||
if let Some(debug) = debug {
|
||||
if let Some(location) = &self.data.location {
|
||||
writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
|
||||
@ -176,7 +188,9 @@ impl TerminatorKind {
|
||||
impl DebugMetadataValue {
|
||||
fn hr(&self, debug: &DebugInformation) -> String {
|
||||
let kind = match debug.get_metadata(*self) {
|
||||
DebugMetadata::ParamVar(DebugParamVariable { name, arg_idx, ty, .. }) => {
|
||||
DebugMetadata::ParamVar(DebugParamVariable {
|
||||
name, arg_idx, ty, ..
|
||||
}) => {
|
||||
format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty)
|
||||
}
|
||||
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
|
||||
@ -241,7 +255,10 @@ impl Debug for FunctionHolder {
|
||||
impl Debug for BlockHolder {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let deleted = if self.data.deleted { " (deleted)" } else { "" };
|
||||
f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted))
|
||||
f.debug_tuple(&format!(
|
||||
"{}[{:?}]{} ",
|
||||
&self.data.name, &self.value, deleted
|
||||
))
|
||||
.field(&self.instructions)
|
||||
.field(&self.data.terminator)
|
||||
.field(&self.data.terminator_location)
|
||||
@ -288,7 +305,11 @@ impl Debug for BlockValue {
|
||||
|
||||
impl Debug for InstructionValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "%{}.{}.{}.{}", self.0.0.0.0, self.0.0.1, self.0.1, self.1)
|
||||
write!(
|
||||
f,
|
||||
"%{}.{}.{}.{}",
|
||||
self.0.0.0.0, self.0.0.1, self.0.1, self.1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +371,9 @@ impl Debug for Instr {
|
||||
fmt_index(f, instruction_value, &index.to_string())?;
|
||||
write!(f, ")")
|
||||
}
|
||||
Instr::ExtractValue(instruction_value, index) => fmt_index(f, instruction_value, &index.to_string()),
|
||||
Instr::ExtractValue(instruction_value, index) => {
|
||||
fmt_index(f, instruction_value, &index.to_string())
|
||||
}
|
||||
Instr::Trunc(instr_val, ty) => {
|
||||
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
|
||||
}
|
||||
@ -394,6 +417,8 @@ impl Debug for Instr {
|
||||
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
|
||||
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
|
||||
Instr::IsNull(_) => write!(f, "is_null"),
|
||||
Instr::Function(function_value) => write!(f, "func {:?}", function_value),
|
||||
Instr::DynFunctionCall(fun, params) => fmt_call(f, fun, params),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,7 +590,11 @@ impl Debug for DebugScopeValue {
|
||||
write!(
|
||||
f,
|
||||
"Scope[{}]",
|
||||
self.0.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ")
|
||||
self.0
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,9 @@ impl LLVMIntrinsic {
|
||||
LLVMIntrinsic::Max(ty) => {
|
||||
let name = match ty.category() {
|
||||
TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => {
|
||||
format!("llvm.umax.{}", ty.llvm_ty_str(builder))
|
||||
}
|
||||
TypeCategory::Real => format!("llvm.maximum.{}", ty.llvm_ty_str(builder)),
|
||||
_ => return Err(crate::ErrorKind::Null),
|
||||
};
|
||||
@ -45,7 +47,9 @@ impl LLVMIntrinsic {
|
||||
LLVMIntrinsic::Min(ty) => {
|
||||
let name = match ty.category() {
|
||||
TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => {
|
||||
format!("llvm.umin.{}", ty.llvm_ty_str(builder))
|
||||
}
|
||||
TypeCategory::Real => format!("llvm.minimum.{}", ty.llvm_ty_str(builder)),
|
||||
_ => return Err(crate::ErrorKind::Null),
|
||||
};
|
||||
@ -54,7 +58,9 @@ impl LLVMIntrinsic {
|
||||
LLVMIntrinsic::Abs(ty) => {
|
||||
let name = match ty.category() {
|
||||
TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)),
|
||||
TypeCategory::UnsignedInteger => {
|
||||
format!("llvm.abs.{}", ty.llvm_ty_str(builder))
|
||||
}
|
||||
TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)),
|
||||
_ => return Err(crate::ErrorKind::Null),
|
||||
};
|
||||
@ -65,7 +71,11 @@ impl LLVMIntrinsic {
|
||||
TypeCategory::Ptr => String::from("llvm.memcpy"),
|
||||
_ => return Err(crate::ErrorKind::Null),
|
||||
};
|
||||
Ok((name, vec![ty.clone(), ty.clone(), Type::U64, Type::Bool], Type::Void))
|
||||
Ok((
|
||||
name,
|
||||
vec![ty.clone(), ty.clone(), Type::U64, Type::Bool],
|
||||
Type::Void,
|
||||
))
|
||||
}
|
||||
LLVMIntrinsic::Sqrt(ty) => {
|
||||
let name = match ty.category() {
|
||||
@ -77,10 +87,18 @@ impl LLVMIntrinsic {
|
||||
LLVMIntrinsic::PowI(ty1, ty2) => {
|
||||
let name = match (ty1.category(), ty2.category()) {
|
||||
(TypeCategory::Real, TypeCategory::SignedInteger) => {
|
||||
format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder))
|
||||
format!(
|
||||
"llvm.powi.{}.{}",
|
||||
ty1.llvm_ty_str(builder),
|
||||
ty2.llvm_ty_str(builder)
|
||||
)
|
||||
}
|
||||
(TypeCategory::Real, TypeCategory::UnsignedInteger) => {
|
||||
format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder))
|
||||
format!(
|
||||
"llvm.powi.{}.{}",
|
||||
ty1.llvm_ty_str(builder),
|
||||
ty2.llvm_ty_str(builder)
|
||||
)
|
||||
}
|
||||
_ => return Err(crate::ErrorKind::Null),
|
||||
};
|
||||
@ -258,6 +276,14 @@ impl Type {
|
||||
}
|
||||
Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)),
|
||||
Type::Ptr(_) => String::from("ptr"),
|
||||
Type::Function(params, ret) => format!(
|
||||
"fn {:?} -> {}",
|
||||
params
|
||||
.iter()
|
||||
.map(|v| v.llvm_ty_str(builder))
|
||||
.collect::<Vec<_>>(),
|
||||
ret.llvm_ty_str(builder)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
src/lib.rs
63
src/lib.rs
@ -164,7 +164,10 @@ impl<'ctx> Module<'ctx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_debug_info(&mut self, file: DebugFileData) -> (DebugInformation, DebugScopeValue) {
|
||||
pub fn create_debug_info(
|
||||
&mut self,
|
||||
file: DebugFileData,
|
||||
) -> (DebugInformation, DebugScopeValue) {
|
||||
let (debug_info, scope_value) = DebugInformation::from_file(file);
|
||||
self.debug_info = Some(debug_info.clone());
|
||||
(debug_info, scope_value)
|
||||
@ -327,12 +330,18 @@ impl Instr {
|
||||
Instr::ShiftLeft(..) => "shl",
|
||||
Instr::GetGlobal(..) => "global",
|
||||
Instr::IsNull(..) => "is_null",
|
||||
Instr::Function(..) => "func",
|
||||
Instr::DynFunctionCall(..) => "call",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'builder> Block<'builder> {
|
||||
pub fn build_named<T: Into<String>>(&mut self, name: T, instruction: Instr) -> CompileResult<InstructionValue> {
|
||||
pub fn build_named<T: Into<String>>(
|
||||
&mut self,
|
||||
name: T,
|
||||
instruction: Instr,
|
||||
) -> CompileResult<InstructionValue> {
|
||||
unsafe {
|
||||
self.builder.add_instruction(
|
||||
&self.value,
|
||||
@ -367,13 +376,15 @@ impl<'builder> Block<'builder> {
|
||||
|
||||
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
|
||||
unsafe {
|
||||
self.builder.add_instruction_location(&instruction, location);
|
||||
self.builder
|
||||
.add_instruction_location(&instruction, location);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) {
|
||||
unsafe {
|
||||
self.builder.add_instruction_metadata(&instruction, location);
|
||||
self.builder
|
||||
.add_instruction_metadata(&instruction, location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,6 +436,7 @@ pub enum Instr {
|
||||
Param(usize),
|
||||
Constant(ConstValueKind),
|
||||
GetGlobal(GlobalValue),
|
||||
Function(FunctionValue),
|
||||
|
||||
/// Add two integers
|
||||
Add(InstructionValue, InstructionValue),
|
||||
@ -524,6 +536,7 @@ pub enum Instr {
|
||||
IsNull(InstructionValue),
|
||||
|
||||
FunctionCall(FunctionValue, Vec<InstructionValue>),
|
||||
DynFunctionCall(InstructionValue, Vec<InstructionValue>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)]
|
||||
@ -550,6 +563,7 @@ pub enum Type {
|
||||
CustomType(TypeValue),
|
||||
Array(Box<Type>, u64),
|
||||
Ptr(Box<Type>),
|
||||
Function(Vec<Type>, Box<Type>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -666,16 +680,25 @@ impl TypeCategory {
|
||||
impl Type {
|
||||
pub fn category(&self) -> TypeCategory {
|
||||
match self {
|
||||
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger,
|
||||
Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger,
|
||||
Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => {
|
||||
TypeCategory::Real
|
||||
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => {
|
||||
TypeCategory::SignedInteger
|
||||
}
|
||||
Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => {
|
||||
TypeCategory::UnsignedInteger
|
||||
}
|
||||
Type::F16
|
||||
| Type::F32B
|
||||
| Type::F32
|
||||
| Type::F64
|
||||
| Type::F80
|
||||
| Type::F128
|
||||
| Type::F128PPC => TypeCategory::Real,
|
||||
Type::Bool => TypeCategory::UnsignedInteger,
|
||||
Type::Void => TypeCategory::Void,
|
||||
Type::CustomType(_) => TypeCategory::CustomType,
|
||||
Type::Array(_, _) => TypeCategory::Array,
|
||||
Type::Ptr(_) => TypeCategory::Ptr,
|
||||
Type::Function(..) => TypeCategory::Ptr,
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,15 +709,23 @@ impl Type {
|
||||
(I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())),
|
||||
(I32, I64 | I128) => Some(Instr::SExt(value, other.clone())),
|
||||
(I64, I128) => Some(Instr::SExt(value, other.clone())),
|
||||
(I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
||||
(I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
||||
(I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
|
||||
Some(Instr::Trunc(value, other.clone()))
|
||||
}
|
||||
(I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => {
|
||||
Some(Instr::Trunc(value, other.clone()))
|
||||
}
|
||||
(I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
||||
(I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
||||
(U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
|
||||
Some(Instr::ZExt(value, other.clone()))
|
||||
}
|
||||
(U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
||||
(U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
||||
(U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
|
||||
Some(Instr::ZExt(value, other.clone()))
|
||||
}
|
||||
(U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => {
|
||||
Some(Instr::ZExt(value, other.clone()))
|
||||
}
|
||||
(U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
||||
(U128 | I128, U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
||||
(U8 | U16 | U32 | U64 | U128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => {
|
||||
@ -715,11 +746,15 @@ impl Type {
|
||||
(Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
|
||||
Some(Instr::PtrToInt(value, other.clone()))
|
||||
}
|
||||
(F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
|
||||
(F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => {
|
||||
Some(Instr::FPExt(value, other.clone()))
|
||||
}
|
||||
(F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
|
||||
(F64, F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
|
||||
(F80, F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
|
||||
(F128PPC | F128, F80 | F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||
(F128PPC | F128, F80 | F64 | F32B | F32 | F16) => {
|
||||
Some(Instr::FPTrunc(value, other.clone()))
|
||||
}
|
||||
(F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||
(F64, F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||
(F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user