Skip to content

Inkwell update to 0.5 #1274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ plc_diagnostics = { path = "./compiler/plc_diagnostics" }
plc_index = { path = "./compiler/plc_index" }
section_mangler = { path = "./compiler/section_mangler" }
logos = "0.12.0"
thiserror = "1.0"
clap = { version = "3.0", features = ["derive"] }
indexmap = "2.0"
generational-arena = "0.2.8"
Expand All @@ -35,6 +34,7 @@ lld_rs = "140.0.0"
which = "4.2.5"
log.workspace = true
inkwell.workspace = true
thiserror.workspace = true
chrono.workspace = true
itertools.workspace = true
anyhow.workspace = true
Expand Down Expand Up @@ -79,7 +79,7 @@ members = [
default-members = [".", "compiler/plc_driver", "compiler/plc_xml"]

[workspace.dependencies]
inkwell = { version = "0.2", features = ["llvm14-0"] }
inkwell = { version = "0.5", features = ["llvm14-0"] }
encoding_rs = "0.8"
encoding_rs_io = "0.1"
log = "0.4"
Expand All @@ -91,3 +91,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
toml = "0.5"
rustc-hash = "1.1.0"
thiserror = "1.0"
3 changes: 2 additions & 1 deletion compiler/plc_diagnostics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ toml.workspace = true
anyhow.workspace = true
lazy_static.workspace = true
log.workspace = true
rustc-hash.workspace = true
rustc-hash.workspace = true
thiserror.workspace = true
9 changes: 2 additions & 7 deletions compiler/plc_diagnostics/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub enum Severity {
/// The `Diagnostics` struct describes an issue encountered during compile time.
/// The issue is defined by an `error_code` and had a defined `severity`
/// Diagnostic severity can be overridden when being reported.
#[derive(Debug)]
#[derive(thiserror::Error, Debug)]
pub struct Diagnostic {
/// The Description of the error being reported.
message: String,
Expand All @@ -40,15 +40,10 @@ pub struct Diagnostic {
/// Children of the current diagnostic
sub_diagnostics: Vec<Diagnostic>,
/// If the diagnostic is caused by an error, this field contains the original error
#[source]
internal_error: Option<anyhow::Error>,
}

impl std::error::Error for Diagnostic {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.internal_error.as_ref().and_then(|it| it.source())
}
}

impl From<std::io::Error> for Diagnostic {
fn from(value: std::io::Error) -> Self {
Diagnostic::new(value.to_string()).with_error_code("E002").with_internal_error(value.into())
Expand Down
5 changes: 4 additions & 1 deletion compiler/plc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,10 @@ pub fn compile_with_options(compile_options: CompilationContext) -> Result<()> {
// 5 : Codegen
if !compile_parameters.is_check() {
let res = generate(&compile_options, &link_options, compile_parameters.target, annotated_project)
.map_err(|err| Diagnostic::codegen_error(err.get_message(), err.get_location()));
.map_err(|err| {
Diagnostic::codegen_error(err.get_message(), err.get_location())
.with_internal_error(err.into())
});
if let Err(res) = res {
diagnostician.handle(&[res]);
return Err(Diagnostic::new("Compilation aborted due to previous errors")
Expand Down
46 changes: 28 additions & 18 deletions src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use plc_source::source_location::{SourceLocation, SourceLocationFactory};
use rustc_hash::FxHashMap;

use crate::{
codegen::diagnostics::CodegenDiagnostic,
codegen::generators::expression_generator::{self, ExpressionCodeGenerator, ExpressionValue},
index::Index,
lexer, parser,
Expand Down Expand Up @@ -50,7 +51,7 @@ lazy_static! {
if let [reference] = params {
generator
.generate_lvalue(reference)
.map(|it| ExpressionValue::RValue(it.as_basic_value_enum()))
.and_then(|it| Ok(ExpressionValue::RValue(it.as_basic_value_enum())))
} else {
Err(Diagnostic::codegen_error(
"Expected exactly one parameter for REF",
Expand Down Expand Up @@ -138,7 +139,7 @@ lazy_static! {
.and_then(|it| generator.get_type_hint_info_for(it))?;
//Create a temp var
let result_type = generator.llvm_index.get_associated_type(type_hint.get_name())?;
let result_var = generator.llvm.create_local_variable("", &result_type);
let result_var = generator.llvm.create_local_variable("", &result_type)?;
let k = generator.generate_expression(k)?;

let mut blocks = vec![];
Expand All @@ -152,12 +153,12 @@ lazy_static! {
let value = context.i32_type().const_int(index as u64, false);
builder.position_at_end(block);
generator.generate_store(result_var, type_hint.get_type_information(), it)?;
builder.build_unconditional_branch(continue_block);
builder.build_unconditional_branch(continue_block).map_err(CodegenDiagnostic::from)?;
Ok((value,block))
}).collect::<Result<Vec<_>,_>>()?;

builder.position_at_end(insert_block);
builder.build_switch(k.into_int_value(), continue_block, &cases);
builder.build_switch(k.into_int_value(), continue_block, &cases).map_err(CodegenDiagnostic::from)?;
builder.position_at_end(continue_block);
Ok(ExpressionValue::LValue(result_var))
} else {
Expand All @@ -183,7 +184,7 @@ lazy_static! {
code: |generator, params, location| {
if let &[g,in0,in1] = params {
// evaluate the parameters
let cond = expression_generator::to_i1(generator.generate_expression(g)?.into_int_value(), &generator.llvm.builder);
let cond = expression_generator::to_i1(generator.generate_expression(g)?.into_int_value(), &generator.llvm.builder)?;
// for aggregate types we need a ptr to perform memcpy
// use generate_expression_value(), this will return a gep
// generate_expression() would load the ptr
Expand All @@ -198,7 +199,7 @@ lazy_static! {
generator.generate_expression(in1)?
};
// generate an llvm select instruction
let sel = generator.llvm.builder.build_select(cond, in1, in0, "");
let sel = generator.llvm.builder.build_select(cond, in1, in0, "").map_err(CodegenDiagnostic::from)?;

if sel.is_pointer_value(){
Ok(ExpressionValue::LValue(sel.into_pointer_value()))
Expand Down Expand Up @@ -890,26 +891,35 @@ fn generate_variable_length_array_bound_function<'ink>(
todo!()
};
// this operation mirrors the offset calculation of literal ints, but at runtime
let offset = builder.build_int_mul(
llvm.i32_type().const_int(2, false),
builder.build_int_sub(
expression_value.into_int_value(),
llvm.i32_type().const_int(1, false),
let offset = builder
.build_int_mul(
llvm.i32_type().const_int(2, false),
builder
.build_int_sub(
expression_value.into_int_value(),
llvm.i32_type().const_int(1, false),
"",
)
.map_err(CodegenDiagnostic::from)?,
"",
),
"",
);
)
.map_err(CodegenDiagnostic::from)?;
if !is_lower {
builder.build_int_add(offset, llvm.i32_type().const_int(1, false), "")
builder
.build_int_add(offset, llvm.i32_type().const_int(1, false), "")
.map_err(CodegenDiagnostic::from)?
} else {
offset
}
}
};

let gep_bound =
unsafe { llvm.builder.build_in_bounds_gep(dim, &[llvm.i32_type().const_zero(), accessor], "") };
let bound = llvm.builder.build_load(gep_bound, "");
let gep_bound = unsafe {
llvm.builder
.build_in_bounds_gep(dim, &[llvm.i32_type().const_zero(), accessor], "")
.map_err(CodegenDiagnostic::from)?
};
let bound = llvm.builder.build_load(gep_bound, "").map_err(CodegenDiagnostic::from)?;

Ok(ExpressionValue::RValue(bound))
}
Expand Down
12 changes: 11 additions & 1 deletion src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use inkwell::{
context::Context,
execution_engine::{ExecutionEngine, JitFunction},
memory_buffer::MemoryBuffer,
types::BasicType,
types::{BasicType, FunctionType},
values::BasicValue,
AddressSpace,
};
Expand All @@ -45,6 +45,7 @@ use plc_diagnostics::diagnostics::Diagnostic;
use plc_source::source_location::SourceLocation;

mod debug;
pub(crate) mod diagnostics;
pub(crate) mod generators;
mod llvm_index;
mod llvm_typesystem;
Expand Down Expand Up @@ -116,6 +117,14 @@ impl<'ink> CodeGen<'ink> {
) -> Result<LlvmTypedIndex<'ink>, Diagnostic> {
let llvm = Llvm::new(context, context.create_builder());
let mut index = LlvmTypedIndex::default();
//Create an init function and position builder there
//TODO: This will conflict with the planned init function
let init_module = llvm.context.create_module("Init");
let void_type = llvm.context.void_type();
let fn_type = void_type.fn_type(&[], false);
let init_func = init_module.add_function("__init", fn_type, None);
let basic_block = llvm.context.append_basic_block(init_func, "entry");
llvm.builder.position_at_end(basic_block);
//Generate types index, and any global variables associated with them.
let llvm_type_index = data_type_generator::generate_data_types(
&llvm,
Expand All @@ -136,6 +145,7 @@ impl<'ink> CodeGen<'ink> {
&self.online_change,
);

//Create a block for the inittializers
//Generate global variables
let llvm_gv_index =
variable_generator.generate_global_variables(dependencies, &self.module_location)?;
Expand Down
38 changes: 38 additions & 0 deletions src/codegen/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::{backtrace, fmt::Display};

use inkwell::builder::BuilderError;
use plc_diagnostics::diagnostics::Diagnostic;
use plc_source::source_location::SourceLocation;
use thiserror::Error;

#[derive(Error, Debug)]
pub struct CodegenDiagnostic {
message: String,
source: BuilderError,
location: SourceLocation,
}

impl Display for CodegenDiagnostic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Codegen error: {}. Source: {} at {}", &self.message, &self.source, &self.location)
}
}

impl From<BuilderError> for CodegenDiagnostic {
fn from(source: BuilderError) -> Self {
// println!("Backtrace: {} ", backtrace::Backtrace::force_capture());
CodegenDiagnostic { message: source.to_string(), source, location: SourceLocation::undefined() }
}
}

impl CodegenDiagnostic {
pub(crate) fn with_location(self, location: SourceLocation) -> CodegenDiagnostic {
CodegenDiagnostic { location, ..self }
}
}

impl From<CodegenDiagnostic> for Diagnostic {
fn from(value: CodegenDiagnostic) -> Self {
Diagnostic::codegen_error(&value.message, value.location.clone()).with_internal_error(value.into())
}
}
Loading
Loading