Skip to content

Commit

Permalink
Multidef!
Browse files Browse the repository at this point in the history
  • Loading branch information
RedstoneWizard08 committed Mar 7, 2024
1 parent abff154 commit 6f128b7
Show file tree
Hide file tree
Showing 28 changed files with 1,387 additions and 73 deletions.
49 changes: 27 additions & 22 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cranelift-entity = "0.105.2"
wasmtime-jit-icache-coherence = "18.0.2"
log = "0.4.20"
notify = "6.1.1"
object = { version = "0.32.2", features = ["write"] }
object = { version = "0.33.0", features = ["write"] }
pretty_env_logger = "0.5.0"
rand = "0.8.5"
target-lexicon = "0.12.13"
Expand All @@ -47,8 +47,8 @@ qsc-jit = { path = "./crates/qsc-jit" }
qsc-lexer = { path = "./crates/qsc-lexer" }
qsc-linker = { path = "./crates/qsc-linker" }
qsc-lsp = { path = "./crates/qsc-lsp" }
qsc-object = { path = "./crates/qsc-object" }
qsc-processor = { path = "./crates/qsc-processor" }
qsc-preprocessor = { path = "./crates/qsc-preprocessor" }

[profile.release]
strip = true
Expand All @@ -68,6 +68,6 @@ members = [
"crates/qsc-lexer",
"crates/qsc-linker",
"crates/qsc-lsp",
"crates/qsc-preprocessor",
"crates/qsc-object",
"crates/qsc-processor",
]
16 changes: 16 additions & 0 deletions crates/qsc-ast/src/ast/decl/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ pub struct FunctionNode<'i> {
pub vis: Visibility,
}

impl<'i> FunctionNode<'i> {
pub fn vars(&self) -> Vec<VariableNode<'i>> {
let mut vars = Vec::new();

for node in &self.content.data {
if let Ok(decl) = node.data.as_decl() {
if let Ok(var) = decl.as_variable() {
vars.push(var);
}
}
}

vars
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct FunctionArgument<'i> {
pub span: Span<'i>,
Expand Down
3 changes: 3 additions & 0 deletions crates/qsc-ast/src/ast/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! The initial Abstract Syntax Tree.
//! This is the container for the raw data that comes from pest's parsing.

pub mod decl;
pub mod expr;
pub mod literal;
Expand Down
1 change: 1 addition & 0 deletions crates/qsc-ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub extern crate miette;

pub mod ast;
pub mod macros;
pub mod processed;
3 changes: 3 additions & 0 deletions crates/qsc-ast/src/processed/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! The Processed Syntax Tree.
//! This is the AST that contains data about type inferences,
//! validated syntax, and more information about the code.
2 changes: 1 addition & 1 deletion crates/qsc-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ cranelift-codegen.workspace = true
cranelift-frontend.workspace = true
cranelift-module.workspace = true
cranelift-native.workspace = true
cranelift-object.workspace = true
log.workspace = true
object.workspace = true
target-lexicon.workspace = true
qsc-ast.workspace = true
qsc-core.workspace = true
qsc-jit.workspace = true
qsc-object.workspace = true
parking_lot.workspace = true
debug-ignore.workspace = true
libc.workspace = true
100 changes: 100 additions & 0 deletions crates/qsc-codegen/src/alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use cranelift_codegen::ir;
use cranelift_module::{FuncId, Linkage, Module, ModuleResult};
use object::{
write::{Symbol, SymbolSection},
SymbolFlags, SymbolKind,
};
use qsc_jit::JITModule;
use qsc_object::{
backend::{translate_linkage, validate_symbol},
ObjectModule,
};

pub trait DeclareAliasedFunction {
fn declare_aliased_function(
&mut self,
name: &str,
real_name: &str,
linkage: Linkage,
signature: &ir::Signature,
) -> ModuleResult<FuncId>;
}

impl<M: Module + DeclareAliasedFunction> DeclareAliasedFunction for &mut M {
fn declare_aliased_function(
&mut self,
name: &str,
real_name: &str,
linkage: Linkage,
signature: &ir::Signature,
) -> ModuleResult<FuncId> {
(**self).declare_aliased_function(name, real_name, linkage, signature)
}
}

impl DeclareAliasedFunction for ObjectModule {
fn declare_aliased_function(
&mut self,
name: &str,
real_name: &str,
linkage: Linkage,
signature: &ir::Signature,
) -> ModuleResult<FuncId> {
validate_symbol(name)?;

let (id, linkage) = self
.declarations
.declare_function(name, linkage, signature)?;

let (scope, weak) = translate_linkage(linkage);

if let Some((function, _defined)) = self.functions[id] {
let symbol = self.object.symbol_mut(function);

symbol.scope = scope;
symbol.weak = weak;
} else {
let symbol_id = self.object.add_symbol(Symbol {
name: real_name.as_bytes().to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Text,
scope,
weak,
section: SymbolSection::Undefined,
flags: SymbolFlags::None,
});

self.functions[id] = Some((symbol_id, false));
}

Ok(id)
}
}

impl DeclareAliasedFunction for JITModule {
fn declare_aliased_function(
&mut self,
name: &str,
real_name: &str,
linkage: Linkage,
signature: &ir::Signature,
) -> ModuleResult<FuncId> {
let (id, linkage) = self
.declarations
.declare_function(name, linkage, signature)?;

if self.function_got_entries[id].is_none() && self.isa.flags().is_pic() {
// FIXME populate got entries with a null pointer when defined
let val = if linkage == Linkage::Import {
self.lookup_symbol(real_name).unwrap_or(std::ptr::null())
} else {
std::ptr::null()
};

self.new_func_plt_entry(id, val);
}

Ok(id)
}
}
2 changes: 1 addition & 1 deletion crates/qsc-codegen/src/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{
};
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use cranelift_module::{default_libcall_names, DataDescription, DataId, Linkage, Module};
use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
use qsc_ast::ast::decl::func::FunctionNode;
use qsc_object::{ObjectBuilder, ObjectModule, ObjectProduct};
use target_lexicon::Triple;

pub struct AotGenerator<'a> {
Expand Down
18 changes: 14 additions & 4 deletions crates/qsc-codegen/src/generator/call.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use super::Backend;
use crate::context::{CodegenContext, CompilerContext};
use crate::{
alias::DeclareAliasedFunction,
context::{CodegenContext, CompilerContext},
};
use cranelift_codegen::ir::{AbiParam, Function, InstBuilder, Value};
use cranelift_module::{Linkage, Module};
use miette::{IntoDiagnostic, Result};
use parking_lot::{RwLock, RwLockWriteGuard};
use qsc_ast::ast::{literal::LiteralNode, stmt::call::CallNode};
use qsc_core::util::random_string;

pub trait CallCompiler<'a, 'b, M: Module>: Backend<'a, 'b, M> {
fn compile_call(
Expand All @@ -14,7 +18,9 @@ pub trait CallCompiler<'a, 'b, M: Module>: Backend<'a, 'b, M> {
) -> Result<Value>;
}

impl<'a, 'b, M: Module, T: Backend<'a, 'b, M>> CallCompiler<'a, 'b, M> for T {
impl<'a, 'b, M: Module + DeclareAliasedFunction, T: Backend<'a, 'b, M>> CallCompiler<'a, 'b, M>
for T
{
fn compile_call(
cctx: &RwLock<CompilerContext<'a, M>>,
ctx: &mut CodegenContext<'a, 'b>,
Expand All @@ -25,6 +31,7 @@ impl<'a, 'b, M: Module, T: Backend<'a, 'b, M>> CallCompiler<'a, 'b, M> for T {
let ptr = Self::ptr(cctx);
let mut wctx = cctx.write();
let mut sig = wctx.module.make_signature();
let mut func_name = call.func.to_string();

if wctx.functions.contains_key(call.func) {
let func = wctx.functions.get(call.func).unwrap();
Expand Down Expand Up @@ -95,8 +102,11 @@ impl<'a, 'b, M: Module, T: Backend<'a, 'b, M>> CallCompiler<'a, 'b, M> for T {
})
.collect::<Vec<String>>();

func_name = format!("__qsc::alias::{}_{}", call.func, random_string(8));

debug!(
"Using imported function for call (Linkage::Import): {}({}) -> i32",
"Using imported function for call (name = {}, Linkage::Import): {}({}) -> i32",
func_name,
call.func,
args.join(", ")
);
Expand All @@ -119,7 +129,7 @@ impl<'a, 'b, M: Module, T: Backend<'a, 'b, M>> CallCompiler<'a, 'b, M> for T {

let callee = wctx
.module
.declare_function(&call.func, Linkage::Import, &sig)
.declare_aliased_function(&func_name, &call.func, Linkage::Import, &sig)
.into_diagnostic()?;

let func_ref = unsafe { ((&mut wctx.ctx.func) as *mut Function).as_mut() }.unwrap();
Expand Down
6 changes: 5 additions & 1 deletion crates/qsc-codegen/src/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use qsc_ast::ast::{
stmt::StatementNode,
};

use crate::alias::DeclareAliasedFunction;

use self::{
call::CallCompiler,
literal::LiteralCompiler,
Expand Down Expand Up @@ -49,7 +51,9 @@ pub trait Backend<'a, 'b, M: Module>: BackendInternal<'a, M> {
) -> GlobalValue;
}

impl<'a, 'b, M: Module, T: BackendInternal<'a, M>> Backend<'a, 'b, M> for T {
impl<'a, 'b, M: Module + DeclareAliasedFunction, T: BackendInternal<'a, M>> Backend<'a, 'b, M>
for T
{
fn query_type(cctx: &RwLock<CompilerContext<'a, M>>, ty: String) -> Type {
Self::query_type_with_pointer(Self::ptr(cctx), ty)
}
Expand Down
9 changes: 7 additions & 2 deletions crates/qsc-codegen/src/generator/ret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use cranelift_module::Module;
use miette::Result;
use parking_lot::RwLock;

use crate::context::{CodegenContext, CompilerContext};
use crate::{
alias::DeclareAliasedFunction,
context::{CodegenContext, CompilerContext},
};
use qsc_ast::ast::stmt::{
call::{CallArgument, CallNode},
ret::ReturnNode,
Expand All @@ -20,7 +23,9 @@ pub trait ReturnCompiler<'a, 'b, M: Module>: Backend<'a, 'b, M> {
) -> Result<Value>;
}

impl<'a, 'b, M: Module, T: Backend<'a, 'b, M>> ReturnCompiler<'a, 'b, M> for T {
impl<'a, 'b, M: Module + DeclareAliasedFunction, T: Backend<'a, 'b, M>> ReturnCompiler<'a, 'b, M>
for T
{
fn compile_return(
cctx: &RwLock<CompilerContext<'a, M>>,
ctx: &mut CodegenContext<'a, 'b>,
Expand Down
Loading

0 comments on commit 6f128b7

Please sign in to comment.