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 std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData,
|
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData,
|
||||||
ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
Instr, InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData,
|
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue,
|
||||||
|
InstructionDebugRecordData,
|
||||||
},
|
},
|
||||||
util::match_types,
|
util::match_types,
|
||||||
};
|
};
|
||||||
@ -114,7 +115,11 @@ impl Builder {
|
|||||||
value
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(mod_val.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(mod_val.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(module.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(module.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(value.0.0.0.0);
|
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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(value.0.0);
|
let module = modules.get_unchecked_mut(value.0.0);
|
||||||
@ -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 {
|
unsafe {
|
||||||
let mut modules = self.modules.borrow_mut();
|
let mut modules = self.modules.borrow_mut();
|
||||||
let module = modules.get_unchecked_mut(block.0.0.0);
|
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) {
|
for (a, b) in param_types.iter().zip(params) {
|
||||||
if *a != b.get_type(&self)? {
|
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(())
|
Ok(())
|
||||||
@ -662,6 +706,14 @@ impl Builder {
|
|||||||
Err(ErrorKind::NotPointer(val, val_ty))
|
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
|
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 {
|
unsafe {
|
||||||
if let Some(location) = location {
|
if let Some(location) = location {
|
||||||
block.builder.add_instruction_location(&self, location);
|
block.builder.add_instruction_location(&self, location);
|
||||||
@ -822,6 +878,17 @@ impl InstructionValue {
|
|||||||
Ok(kind.get_type())
|
Ok(kind.get_type())
|
||||||
}
|
}
|
||||||
IsNull(_) => Ok(Type::Bool),
|
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,
|
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
|
||||||
},
|
},
|
||||||
target_machine::{
|
target_machine::{
|
||||||
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple,
|
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
|
||||||
LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
|
LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,8 +35,8 @@ use crate::{
|
|||||||
use super::{
|
use super::{
|
||||||
CmpPredicate, ConstValueKind, Context, TerminatorKind, Type,
|
CmpPredicate, ConstValueKind, Context, TerminatorKind, Type,
|
||||||
builder::{
|
builder::{
|
||||||
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue,
|
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder,
|
||||||
ModuleHolder,
|
InstructionValue, ModuleHolder,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,8 +120,8 @@ impl CompiledModule {
|
|||||||
);
|
);
|
||||||
err.into_result().unwrap();
|
err.into_result().unwrap();
|
||||||
|
|
||||||
let llvm_ir =
|
let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref))
|
||||||
from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string");
|
.expect("Unable to print LLVM IR to string");
|
||||||
|
|
||||||
let mut err = ErrorMessageHolder::null();
|
let mut err = ErrorMessageHolder::null();
|
||||||
LLVMVerifyModule(
|
LLVMVerifyModule(
|
||||||
@ -231,8 +231,10 @@ pub struct LLVMValue {
|
|||||||
impl ModuleHolder {
|
impl ModuleHolder {
|
||||||
fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef {
|
fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let module_ref =
|
let module_ref = LLVMModuleCreateWithNameInContext(
|
||||||
LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref);
|
into_cstring(&self.data.name).as_ptr(),
|
||||||
|
context.context_ref,
|
||||||
|
);
|
||||||
|
|
||||||
// Compile the contents
|
// Compile the contents
|
||||||
|
|
||||||
@ -327,9 +329,12 @@ impl ModuleHolder {
|
|||||||
constant.value,
|
constant.value,
|
||||||
LLVMValue {
|
LLVMValue {
|
||||||
ty: constant.kind.get_type(),
|
ty: constant.kind.get_type(),
|
||||||
value_ref: constant
|
value_ref: constant.kind.as_llvm(
|
||||||
.kind
|
context.context_ref,
|
||||||
.as_llvm(context.context_ref, context.builder_ref, &constants, &types),
|
context.builder_ref,
|
||||||
|
&constants,
|
||||||
|
&types,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -357,7 +362,12 @@ impl ModuleHolder {
|
|||||||
scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i));
|
scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i));
|
||||||
}
|
}
|
||||||
for scope in &scope.inner_scopes {
|
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 {
|
impl DebugLocationHolder {
|
||||||
unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
|
unsafe fn compile(
|
||||||
|
&self,
|
||||||
|
context: &LLVMContext,
|
||||||
|
debug: &LLVMDebugInformation,
|
||||||
|
) -> LLVMMetadataRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
LLVMDIBuilderCreateDebugLocation(
|
LLVMDIBuilderCreateDebugLocation(
|
||||||
context.context_ref,
|
context.context_ref,
|
||||||
@ -515,7 +529,8 @@ impl DebugTypeHolder {
|
|||||||
ptr.name.len(),
|
ptr.name.len(),
|
||||||
),
|
),
|
||||||
DebugTypeData::Array(array) => {
|
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];
|
let mut elements = vec![subrange];
|
||||||
LLVMDIBuilderCreateArrayType(
|
LLVMDIBuilderCreateArrayType(
|
||||||
debug.builder,
|
debug.builder,
|
||||||
@ -577,7 +592,11 @@ impl DwarfFlags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeHolder {
|
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 {
|
unsafe {
|
||||||
match &self.data.kind {
|
match &self.data.kind {
|
||||||
CustomTypeKind::NamedStruct(named_struct) => {
|
CustomTypeKind::NamedStruct(named_struct) => {
|
||||||
@ -585,9 +604,16 @@ impl TypeHolder {
|
|||||||
for ty in &named_struct.1 {
|
for ty in &named_struct.1 {
|
||||||
elem_types.push(ty.as_llvm(context.context_ref, types));
|
elem_types.push(ty.as_llvm(context.context_ref, types));
|
||||||
}
|
}
|
||||||
let struct_ty =
|
let struct_ty = LLVMStructCreateNamed(
|
||||||
LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr());
|
context.context_ref,
|
||||||
LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0);
|
into_cstring(named_struct.0.clone()).as_ptr(),
|
||||||
|
);
|
||||||
|
LLVMStructSetBody(
|
||||||
|
struct_ty,
|
||||||
|
elem_types.as_mut_ptr(),
|
||||||
|
elem_types.len() as u32,
|
||||||
|
0,
|
||||||
|
);
|
||||||
struct_ty
|
struct_ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -617,7 +643,13 @@ impl FunctionHolder {
|
|||||||
let name = if self.data.flags.is_main {
|
let name = if self.data.flags.is_main {
|
||||||
c"main"
|
c"main"
|
||||||
} else {
|
} 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);
|
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);
|
let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type);
|
||||||
|
|
||||||
if self.data.flags.inline {
|
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);
|
LLVMAddAttributeAtIndex(function_ref, 0, attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,7 +724,10 @@ impl FunctionHolder {
|
|||||||
|
|
||||||
if self.data.flags.is_imported {
|
if self.data.flags.is_imported {
|
||||||
if self.data.flags.is_extern {
|
if self.data.flags.is_extern {
|
||||||
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage);
|
LLVMSetLinkage(
|
||||||
|
own_function.value_ref,
|
||||||
|
LLVMLinkage::LLVMAvailableExternallyLinkage,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
|
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
|
||||||
}
|
}
|
||||||
@ -705,8 +744,10 @@ impl FunctionHolder {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_ref =
|
let block_ref = LLVMCreateBasicBlockInContext(
|
||||||
LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr());
|
module.context_ref,
|
||||||
|
into_cstring(&block.data.name).as_ptr(),
|
||||||
|
);
|
||||||
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
|
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
|
||||||
module.blocks.insert(block.value, block_ref);
|
module.blocks.insert(block.value, block_ref);
|
||||||
}
|
}
|
||||||
@ -738,13 +779,22 @@ impl BlockHolder {
|
|||||||
.data
|
.data
|
||||||
.terminator
|
.terminator
|
||||||
.clone()
|
.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);
|
.compile(module, function, block_ref);
|
||||||
|
|
||||||
if let Some(location) = &self.data.terminator_location {
|
if let Some(location) = &self.data.terminator_location {
|
||||||
LLVMInstructionSetDebugLoc(
|
LLVMInstructionSetDebugLoc(
|
||||||
term_instr.value_ref,
|
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 {
|
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 _ty = self.value.get_type(module.builder).unwrap();
|
||||||
let name = into_cstring(self.name.clone());
|
let name = into_cstring(self.name.clone());
|
||||||
let val = unsafe {
|
let val = unsafe {
|
||||||
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.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) => {
|
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;
|
||||||
@ -1055,6 +1115,34 @@ impl InstructionHolder {
|
|||||||
let val = module.values.get(&*instruction_value).unwrap().value_ref;
|
let val = module.values.get(&*instruction_value).unwrap().value_ref;
|
||||||
LLVMBuildIsNull(module.builder_ref, val, name.as_ptr())
|
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 {
|
if let Some(record) = &self.record {
|
||||||
@ -1062,7 +1150,8 @@ impl InstructionHolder {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut addr = Vec::<u64>::new();
|
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(
|
let location = LLVMDIBuilderCreateDebugLocation(
|
||||||
module.context_ref,
|
module.context_ref,
|
||||||
@ -1073,22 +1162,26 @@ impl InstructionHolder {
|
|||||||
);
|
);
|
||||||
|
|
||||||
match record.kind {
|
match record.kind {
|
||||||
DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore(
|
DebugRecordKind::Declare(instruction_value) => {
|
||||||
|
LLVMDIBuilderInsertDeclareRecordBefore(
|
||||||
debug.builder,
|
debug.builder,
|
||||||
module.values.get(&instruction_value).unwrap().value_ref,
|
module.values.get(&instruction_value).unwrap().value_ref,
|
||||||
*debug.metadata.get(&record.variable).unwrap(),
|
*debug.metadata.get(&record.variable).unwrap(),
|
||||||
expr,
|
expr,
|
||||||
location,
|
location,
|
||||||
val,
|
val,
|
||||||
),
|
)
|
||||||
DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore(
|
}
|
||||||
|
DebugRecordKind::Value(instruction_value) => {
|
||||||
|
LLVMDIBuilderInsertDbgValueRecordBefore(
|
||||||
debug.builder,
|
debug.builder,
|
||||||
module.values.get(&instruction_value).unwrap().value_ref,
|
module.values.get(&instruction_value).unwrap().value_ref,
|
||||||
*debug.metadata.get(&record.variable).unwrap(),
|
*debug.metadata.get(&record.variable).unwrap(),
|
||||||
expr,
|
expr,
|
||||||
location,
|
location,
|
||||||
val,
|
val,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1101,7 +1194,13 @@ impl InstructionHolder {
|
|||||||
| LLVMValueKind::LLVMMemoryPhiValueKind => {
|
| LLVMValueKind::LLVMMemoryPhiValueKind => {
|
||||||
LLVMInstructionSetDebugLoc(
|
LLVMInstructionSetDebugLoc(
|
||||||
val,
|
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 {
|
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 _ty = self.get_type(module.builder).unwrap();
|
||||||
let val = unsafe {
|
let val = unsafe {
|
||||||
match self {
|
match self {
|
||||||
@ -1226,7 +1330,11 @@ impl ConstValueKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
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::*;
|
use Type::*;
|
||||||
unsafe {
|
unsafe {
|
||||||
match self {
|
match self {
|
||||||
@ -1247,6 +1355,18 @@ impl Type {
|
|||||||
F80 => LLVMX86FP80TypeInContext(context),
|
F80 => LLVMX86FP80TypeInContext(context),
|
||||||
F128 => LLVMFP128TypeInContext(context),
|
F128 => LLVMFP128TypeInContext(context),
|
||||||
F128PPC => LLVMPPCFP128TypeInContext(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,
|
CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
|
||||||
builder::*,
|
builder::*,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
|
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable,
|
||||||
DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition,
|
DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable,
|
||||||
DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder,
|
DebugPointerType, DebugPosition, DebugRecordKind, DebugScopeValue, DebugStructType,
|
||||||
DebugTypeValue,
|
DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue,
|
||||||
},
|
},
|
||||||
pad_adapter::PadAdapter,
|
pad_adapter::PadAdapter,
|
||||||
};
|
};
|
||||||
@ -68,7 +68,11 @@ impl FunctionHolder {
|
|||||||
.map(|p| format!("{:?}", p))
|
.map(|p| format!("{:?}", p))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?;
|
write!(
|
||||||
|
f,
|
||||||
|
"fn {}({}) -> {:?} ",
|
||||||
|
self.data.name, params, self.data.ret
|
||||||
|
)?;
|
||||||
|
|
||||||
writeln!(f, "{{")?;
|
writeln!(f, "{{")?;
|
||||||
let mut state = Default::default();
|
let mut state = Default::default();
|
||||||
@ -112,7 +116,11 @@ impl BlockHolder {
|
|||||||
terminator.builder_fmt(&mut inner, builder, debug)?;
|
terminator.builder_fmt(&mut inner, builder, debug)?;
|
||||||
}
|
}
|
||||||
if let Some(location) = &self.data.terminator_location {
|
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(())
|
Ok(())
|
||||||
@ -140,7 +148,11 @@ impl InstructionHolder {
|
|||||||
writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?;
|
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(debug) = debug {
|
||||||
if let Some(location) = &self.data.location {
|
if let Some(location) = &self.data.location {
|
||||||
writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
|
writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
|
||||||
@ -176,7 +188,9 @@ impl TerminatorKind {
|
|||||||
impl DebugMetadataValue {
|
impl DebugMetadataValue {
|
||||||
fn hr(&self, debug: &DebugInformation) -> String {
|
fn hr(&self, debug: &DebugInformation) -> String {
|
||||||
let kind = match debug.get_metadata(*self) {
|
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)
|
format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty)
|
||||||
}
|
}
|
||||||
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
|
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
|
||||||
@ -241,7 +255,10 @@ impl Debug for FunctionHolder {
|
|||||||
impl Debug for BlockHolder {
|
impl Debug for BlockHolder {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let deleted = if self.data.deleted { " (deleted)" } else { "" };
|
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.instructions)
|
||||||
.field(&self.data.terminator)
|
.field(&self.data.terminator)
|
||||||
.field(&self.data.terminator_location)
|
.field(&self.data.terminator_location)
|
||||||
@ -288,7 +305,11 @@ impl Debug for BlockValue {
|
|||||||
|
|
||||||
impl Debug for InstructionValue {
|
impl Debug for InstructionValue {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
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())?;
|
fmt_index(f, instruction_value, &index.to_string())?;
|
||||||
write!(f, ")")
|
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) => {
|
Instr::Trunc(instr_val, ty) => {
|
||||||
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
|
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::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
|
||||||
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
|
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
|
||||||
Instr::IsNull(_) => write!(f, "is_null"),
|
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!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Scope[{}]",
|
"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) => {
|
LLVMIntrinsic::Max(ty) => {
|
||||||
let name = match ty.category() {
|
let name = match ty.category() {
|
||||||
TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)),
|
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)),
|
TypeCategory::Real => format!("llvm.maximum.{}", ty.llvm_ty_str(builder)),
|
||||||
_ => return Err(crate::ErrorKind::Null),
|
_ => return Err(crate::ErrorKind::Null),
|
||||||
};
|
};
|
||||||
@ -45,7 +47,9 @@ impl LLVMIntrinsic {
|
|||||||
LLVMIntrinsic::Min(ty) => {
|
LLVMIntrinsic::Min(ty) => {
|
||||||
let name = match ty.category() {
|
let name = match ty.category() {
|
||||||
TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)),
|
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)),
|
TypeCategory::Real => format!("llvm.minimum.{}", ty.llvm_ty_str(builder)),
|
||||||
_ => return Err(crate::ErrorKind::Null),
|
_ => return Err(crate::ErrorKind::Null),
|
||||||
};
|
};
|
||||||
@ -54,7 +58,9 @@ impl LLVMIntrinsic {
|
|||||||
LLVMIntrinsic::Abs(ty) => {
|
LLVMIntrinsic::Abs(ty) => {
|
||||||
let name = match ty.category() {
|
let name = match ty.category() {
|
||||||
TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)),
|
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)),
|
TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)),
|
||||||
_ => return Err(crate::ErrorKind::Null),
|
_ => return Err(crate::ErrorKind::Null),
|
||||||
};
|
};
|
||||||
@ -65,7 +71,11 @@ impl LLVMIntrinsic {
|
|||||||
TypeCategory::Ptr => String::from("llvm.memcpy"),
|
TypeCategory::Ptr => String::from("llvm.memcpy"),
|
||||||
_ => return Err(crate::ErrorKind::Null),
|
_ => 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) => {
|
LLVMIntrinsic::Sqrt(ty) => {
|
||||||
let name = match ty.category() {
|
let name = match ty.category() {
|
||||||
@ -77,10 +87,18 @@ impl LLVMIntrinsic {
|
|||||||
LLVMIntrinsic::PowI(ty1, ty2) => {
|
LLVMIntrinsic::PowI(ty1, ty2) => {
|
||||||
let name = match (ty1.category(), ty2.category()) {
|
let name = match (ty1.category(), ty2.category()) {
|
||||||
(TypeCategory::Real, TypeCategory::SignedInteger) => {
|
(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) => {
|
(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),
|
_ => return Err(crate::ErrorKind::Null),
|
||||||
};
|
};
|
||||||
@ -258,6 +276,14 @@ impl Type {
|
|||||||
}
|
}
|
||||||
Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)),
|
Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)),
|
||||||
Type::Ptr(_) => String::from("ptr"),
|
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);
|
let (debug_info, scope_value) = DebugInformation::from_file(file);
|
||||||
self.debug_info = Some(debug_info.clone());
|
self.debug_info = Some(debug_info.clone());
|
||||||
(debug_info, scope_value)
|
(debug_info, scope_value)
|
||||||
@ -327,12 +330,18 @@ impl Instr {
|
|||||||
Instr::ShiftLeft(..) => "shl",
|
Instr::ShiftLeft(..) => "shl",
|
||||||
Instr::GetGlobal(..) => "global",
|
Instr::GetGlobal(..) => "global",
|
||||||
Instr::IsNull(..) => "is_null",
|
Instr::IsNull(..) => "is_null",
|
||||||
|
Instr::Function(..) => "func",
|
||||||
|
Instr::DynFunctionCall(..) => "call",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'builder> Block<'builder> {
|
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 {
|
unsafe {
|
||||||
self.builder.add_instruction(
|
self.builder.add_instruction(
|
||||||
&self.value,
|
&self.value,
|
||||||
@ -367,13 +376,15 @@ impl<'builder> Block<'builder> {
|
|||||||
|
|
||||||
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
|
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
|
||||||
unsafe {
|
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) {
|
pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.builder.add_instruction_metadata(&instruction, location);
|
self.builder
|
||||||
|
.add_instruction_metadata(&instruction, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +436,7 @@ pub enum Instr {
|
|||||||
Param(usize),
|
Param(usize),
|
||||||
Constant(ConstValueKind),
|
Constant(ConstValueKind),
|
||||||
GetGlobal(GlobalValue),
|
GetGlobal(GlobalValue),
|
||||||
|
Function(FunctionValue),
|
||||||
|
|
||||||
/// Add two integers
|
/// Add two integers
|
||||||
Add(InstructionValue, InstructionValue),
|
Add(InstructionValue, InstructionValue),
|
||||||
@ -524,6 +536,7 @@ pub enum Instr {
|
|||||||
IsNull(InstructionValue),
|
IsNull(InstructionValue),
|
||||||
|
|
||||||
FunctionCall(FunctionValue, Vec<InstructionValue>),
|
FunctionCall(FunctionValue, Vec<InstructionValue>),
|
||||||
|
DynFunctionCall(InstructionValue, Vec<InstructionValue>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)]
|
||||||
@ -550,6 +563,7 @@ pub enum Type {
|
|||||||
CustomType(TypeValue),
|
CustomType(TypeValue),
|
||||||
Array(Box<Type>, u64),
|
Array(Box<Type>, u64),
|
||||||
Ptr(Box<Type>),
|
Ptr(Box<Type>),
|
||||||
|
Function(Vec<Type>, Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -666,16 +680,25 @@ impl TypeCategory {
|
|||||||
impl Type {
|
impl Type {
|
||||||
pub fn category(&self) -> TypeCategory {
|
pub fn category(&self) -> TypeCategory {
|
||||||
match self {
|
match self {
|
||||||
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger,
|
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => {
|
||||||
Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger,
|
TypeCategory::SignedInteger
|
||||||
Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => {
|
|
||||||
TypeCategory::Real
|
|
||||||
}
|
}
|
||||||
|
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::Bool => TypeCategory::UnsignedInteger,
|
||||||
Type::Void => TypeCategory::Void,
|
Type::Void => TypeCategory::Void,
|
||||||
Type::CustomType(_) => TypeCategory::CustomType,
|
Type::CustomType(_) => TypeCategory::CustomType,
|
||||||
Type::Array(_, _) => TypeCategory::Array,
|
Type::Array(_, _) => TypeCategory::Array,
|
||||||
Type::Ptr(_) => TypeCategory::Ptr,
|
Type::Ptr(_) => TypeCategory::Ptr,
|
||||||
|
Type::Function(..) => TypeCategory::Ptr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,15 +709,23 @@ impl Type {
|
|||||||
(I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())),
|
(I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())),
|
||||||
(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())),
|
(I64, I128) => Some(Instr::SExt(value, other.clone())),
|
||||||
(I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
(I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
|
||||||
(I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
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())),
|
(I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
|
||||||
(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) => {
|
(U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
|
||||||
Some(Instr::ZExt(value, other.clone()))
|
Some(Instr::ZExt(value, other.clone()))
|
||||||
}
|
}
|
||||||
(U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
(U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
|
||||||
(U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
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())),
|
(U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
|
||||||
(U128 | I128, 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) => {
|
(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) => {
|
(Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
|
||||||
Some(Instr::PtrToInt(value, other.clone()))
|
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())),
|
(F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
|
||||||
(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())),
|
(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())),
|
(F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||||
(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())),
|
(F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user