Skip to content

Commit

Permalink
Merge pull request #283 from baszalmstra/feature/pub
Browse files Browse the repository at this point in the history
feature: adds modules and visibility
  • Loading branch information
baszalmstra committed Nov 4, 2020
2 parents b6f6c40 + 9da3be5 commit a45496a
Show file tree
Hide file tree
Showing 87 changed files with 3,296 additions and 1,555 deletions.
2 changes: 1 addition & 1 deletion crates/mun/src/ops/init.rs
Expand Up @@ -41,7 +41,7 @@ version="0.1.0"
let src_path = create_in.join("src");
create_dir(&src_path)?;

let main_file_path = src_path.join("main.mun");
let main_file_path = src_path.join("mod.mun");

write(
&main_file_path,
Expand Down
2 changes: 1 addition & 1 deletion crates/mun/tests/integration.rs
Expand Up @@ -48,7 +48,7 @@ fn build_and_run(project: impl AsRef<Path>) {
];
assert_eq!(run_with_args(args).unwrap(), mun::ExitStatus::Success);

let library_path = project.as_ref().join("target/main.munlib");
let library_path = project.as_ref().join("target/mod.munlib");
assert!(library_path.is_file());

let runtime = RuntimeBuilder::new(&library_path).spawn().unwrap();
Expand Down
4 changes: 2 additions & 2 deletions crates/mun_codegen/src/assembly.rs
Expand Up @@ -34,7 +34,7 @@ impl Assembly {
}

/// Builds an assembly for the specified file
pub(crate) fn build_assembly(db: &dyn CodeGenDatabase, file_id: hir::FileId) -> Arc<Assembly> {
pub(crate) fn build_assembly(db: &dyn CodeGenDatabase, module: hir::Module) -> Arc<Assembly> {
// Construct a temporary file for the assembly
let file = NamedTempFile::new().expect("could not create temp file for shared object");

Expand All @@ -44,7 +44,7 @@ pub(crate) fn build_assembly(db: &dyn CodeGenDatabase, file_id: hir::FileId) ->

// Construct the module
let module_builder =
ModuleBuilder::new(&code_gen_context, file_id).expect("could not create ModuleBuilder");
ModuleBuilder::new(&code_gen_context, module).expect("could not create ModuleBuilder");
let obj_file = module_builder
.build()
.expect("unable to create object file");
Expand Down
14 changes: 8 additions & 6 deletions crates/mun_codegen/src/code_gen/module_builder.rs
Expand Up @@ -3,37 +3,39 @@ use crate::code_gen::{optimize_module, symbols, CodeGenContext, CodeGenerationEr
use crate::ir::file::gen_file_ir;
use crate::ir::file_group::gen_file_group_ir;
use crate::value::{IrTypeContext, IrValueContext};
use hir::FileId;
use inkwell::module::{Linkage, Module};

/// A struct that can be used to build an LLVM `Module`.
pub struct ModuleBuilder<'db, 'ink, 'ctx> {
code_gen: &'ctx CodeGenContext<'db, 'ink>,
file_id: FileId,
module: hir::Module,
assembly_module: Module<'ink>,
}

impl<'db, 'ink, 'ctx> ModuleBuilder<'db, 'ink, 'ctx> {
/// Constructs a module for the given `hir::FileId` using the provided `CodeGenContext`.
pub fn new(
code_gen: &'ctx CodeGenContext<'db, 'ink>,
file_id: FileId,
module: hir::Module,
) -> Result<Self, anyhow::Error> {
// Construct a module for the assembly
let file_id = module
.file_id(code_gen.db)
.expect("module must have a file");
let assembly_name = code_gen.db.file_relative_path(file_id);
let assembly_module = code_gen.create_module(assembly_name);

Ok(Self {
code_gen,
file_id,
module,
assembly_module,
})
}

/// Constructs an object file.
pub fn build(self) -> Result<ObjectFile, anyhow::Error> {
let group_ir = gen_file_group_ir(self.code_gen, self.file_id);
let file = gen_file_ir(self.code_gen, &group_ir, self.file_id);
let group_ir = gen_file_group_ir(self.code_gen, self.module);
let file = gen_file_ir(self.code_gen, &group_ir, self.module);

// Clone the LLVM modules so that we can modify it without modifying the cached value.
self.assembly_module
Expand Down
2 changes: 1 addition & 1 deletion crates/mun_codegen/src/db.rs
Expand Up @@ -22,7 +22,7 @@ pub trait CodeGenDatabase: hir::HirDatabase + hir::Upcast<dyn hir::HirDatabase>
/// Returns a fully linked shared object for the specified group of files.
/// TODO: Current, a group always consists of a single file. Need to add support for multiple.
#[salsa::invoke(crate::assembly::build_assembly)]
fn assembly(&self, file: hir::FileId) -> Arc<Assembly>;
fn assembly(&self, module: hir::Module) -> Arc<Assembly>;
}

/// Constructs the primary interface to the complete machine description for the target machine. All
Expand Down
50 changes: 25 additions & 25 deletions crates/mun_codegen/src/ir/body.rs
Expand Up @@ -7,8 +7,8 @@ use crate::{
};
use hir::{
ArithOp, BinaryOp, Body, CmpOp, Expr, ExprId, HirDatabase, HirDisplay, InferenceResult,
Literal, LogicOp, Name, Ordering, Pat, PatId, Path, Resolution, ResolveBitness, Resolver,
Statement, TypeCtor, UnaryOp,
Literal, LogicOp, Name, Ordering, Pat, PatId, Path, ResolveBitness, Resolver, Statement,
TypeCtor, UnaryOp, ValueNs,
};
use inkwell::{
basic_block::BasicBlock,
Expand Down Expand Up @@ -209,7 +209,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
tail,
} => self.gen_block(expr, statements, *tail),
Expr::Path(ref p) => {
let resolver = hir::resolver_for_expr(self.body.clone(), self.db, expr);
let resolver = hir::resolver_for_expr(self.db.upcast(), self.body.owner(), expr);
Some(self.gen_path_expr(p, expr, &resolver))
}
Expr::Literal(lit) => Some(self.gen_literal(lit, expr)),
Expand Down Expand Up @@ -412,7 +412,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
struct_ir_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic),
&format!("{}_ptr_ptr", hir_struct.name(self.db.upcast()).to_string()),
&format!("{}_ptr_ptr", hir_struct.name(self.db).to_string()),
)
.into_pointer_value();

Expand All @@ -421,7 +421,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
.builder
.build_load(
struct_ptr_ptr,
&format!("{}_mem_ptr", hir_struct.name(self.db.upcast()).to_string()),
&format!("{}_mem_ptr", hir_struct.name(self.db).to_string()),
)
.into_pointer_value();

Expand Down Expand Up @@ -557,13 +557,12 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
expr: ExprId,
resolver: &Resolver,
) -> inkwell::values::BasicValueEnum<'ink> {
let resolution = resolver
.resolve_path_without_assoc_items(self.db, path)
.take_values()
.expect("unknown path");

match resolution {
Resolution::LocalBinding(pat) => {
match resolver
.resolve_path_as_value_fully(self.db.upcast(), path)
.expect("unknown path")
.0
{
ValueNs::LocalBinding(pat) => {
if let Some(param) = self.pat_to_param.get(&pat) {
*param
} else if let Some(ptr) = self.pat_to_local.get(&pat) {
Expand All @@ -573,8 +572,8 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
unreachable!("could not find the pattern..");
}
}
Resolution::Def(hir::ModuleDef::Struct(_)) => self.gen_unit_struct_lit(expr),
Resolution::Def(_) => panic!("no support for module definitions"),
ValueNs::StructId(_) => self.gen_unit_struct_lit(expr),
ValueNs::FunctionId(_) => panic!("unable to generate path expression from a function"),
}
}

Expand Down Expand Up @@ -605,17 +604,18 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
_expr: ExprId,
resolver: &Resolver,
) -> inkwell::values::PointerValue<'ink> {
let resolution = resolver
.resolve_path_without_assoc_items(self.db, path)
.take_values()
.expect("unknown path");

match resolution {
Resolution::LocalBinding(pat) => *self
match resolver
.resolve_path_as_value_fully(self.db.upcast(), path)
.expect("unknown path")
.0
{
ValueNs::LocalBinding(pat) => *self
.pat_to_local
.get(&pat)
.expect("unresolved local binding"),
Resolution::Def(_) => panic!("no support for module definitions"),
ValueNs::FunctionId(_) | ValueNs::StructId(_) => {
panic!("no support for module definitions")
}
}
}

Expand Down Expand Up @@ -1043,7 +1043,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
let body = self.body.clone();
match &body[expr] {
Expr::Path(ref p) => {
let resolver = hir::resolver_for_expr(self.body.clone(), self.db, expr);
let resolver = hir::resolver_for_expr(self.db.upcast(), self.body.owner(), expr);
self.gen_path_place_expr(p, expr, &resolver)
}
Expr::Field {
Expand Down Expand Up @@ -1325,7 +1325,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
.as_struct()
.expect("expected a struct");

let hir_struct_name = hir_struct.name(self.db.upcast());
let hir_struct_name = hir_struct.name(self.db);

let field_idx = hir_struct
.field(self.db, name)
Expand Down Expand Up @@ -1376,7 +1376,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
.as_struct()
.expect("expected a struct");

let hir_struct_name = hir_struct.name(self.db.upcast());
let hir_struct_name = hir_struct.name(self.db);

let field_idx = hir_struct
.field(self.db, name)
Expand Down
33 changes: 19 additions & 14 deletions crates/mun_codegen/src/ir/file.rs
@@ -1,10 +1,12 @@
use super::body::ExternalGlobals;
use crate::code_gen::CodeGenContext;
use crate::ir::body::BodyIrGenerator;
use crate::ir::file_group::FileGroupIR;
use crate::ir::{function, type_table::TypeTable};
use crate::value::Global;
use hir::{FileId, ModuleDef};
use crate::{
code_gen::CodeGenContext,
ir::body::BodyIrGenerator,
ir::file_group::FileGroupIR,
ir::{function, type_table::TypeTable},
value::Global,
};
use hir::{FileId, HasVisibility, ModuleDef};
use inkwell::module::Module;
use std::collections::{BTreeMap, HashMap, HashSet};

Expand All @@ -23,8 +25,11 @@ pub struct FileIR<'ink> {
pub(crate) fn gen_file_ir<'db, 'ink>(
code_gen: &CodeGenContext<'db, 'ink>,
group_ir: &FileGroupIR<'ink>,
file_id: FileId,
module: hir::Module,
) -> FileIR<'ink> {
let file_id = module
.file_id(code_gen.db)
.expect("module must have an associated file");
let llvm_module = code_gen
.context
.create_module(code_gen.db.file_relative_path(file_id).as_str());
Expand All @@ -35,23 +40,23 @@ pub(crate) fn gen_file_ir<'db, 'ink>(
// Use a `BTreeMap` to guarantee deterministically ordered output.ures
let mut functions = HashMap::new();
let mut wrapper_functions = BTreeMap::new();
for def in code_gen.db.module_data(file_id).definitions() {
for def in module.declarations(code_gen.db) {
if let ModuleDef::Function(f) = def {
if !f.is_extern(code_gen.db) {
let fun = function::gen_prototype(code_gen.db, hir_types, *f, &llvm_module);
functions.insert(*f, fun);
let fun = function::gen_prototype(code_gen.db, hir_types, f, &llvm_module);
functions.insert(f, fun);

let fn_sig = f.ty(code_gen.db).callable_sig(code_gen.db).unwrap();
if !f.data(code_gen.db).visibility().is_private()
if f.visibility(code_gen.db).is_externally_visible()
&& !fn_sig.marshallable(code_gen.db)
{
let wrapper_fun = function::gen_public_prototype(
code_gen.db,
&code_gen.hir_types,
*f,
f,
&llvm_module,
);
wrapper_functions.insert(*f, wrapper_fun);
wrapper_functions.insert(f, wrapper_fun);
}
}
}
Expand Down Expand Up @@ -116,7 +121,7 @@ pub(crate) fn gen_file_ir<'db, 'ink>(
// Filter private methods
let api: HashSet<hir::Function> = functions
.keys()
.filter(|f| f.visibility(code_gen.db) != hir::Visibility::Private)
.filter(|f| f.visibility(code_gen.db).is_externally_visible())
.cloned()
.collect();

Expand Down
29 changes: 16 additions & 13 deletions crates/mun_codegen/src/ir/file_group.rs
Expand Up @@ -3,9 +3,11 @@ use super::{
intrinsics,
type_table::{TypeTable, TypeTableBuilder},
};
use crate::code_gen::CodeGenContext;
use crate::value::{IrTypeContext, IrValueContext};
use hir::ModuleDef;
use crate::{
code_gen::CodeGenContext,
value::{IrTypeContext, IrValueContext},
};
use hir::{HasVisibility, ModuleDef};
use inkwell::{module::Module, types::PointerType, values::UnnamedAddress, AddressSpace};
use std::collections::BTreeMap;

Expand All @@ -28,7 +30,7 @@ pub struct FileGroupIR<'ink> {
/// files using something like `FileGroupId`.
pub(crate) fn gen_file_group_ir<'db, 'ink>(
code_gen: &CodeGenContext<'db, 'ink>,
file_id: hir::FileId,
module: hir::Module,
) -> FileGroupIR<'ink> {
let llvm_module = code_gen.context.create_module("group_name");

Expand All @@ -37,7 +39,7 @@ pub(crate) fn gen_file_group_ir<'db, 'ink>(
let mut needs_alloc = false;

// Collect all intrinsic functions, wrapper function, and generate struct declarations.
for def in code_gen.db.module_data(file_id).definitions() {
for def in module.declarations(code_gen.db) {
match def {
ModuleDef::Function(f) if !f.is_extern(code_gen.db) => {
intrinsics::collect_fn_body(
Expand All @@ -51,7 +53,7 @@ pub(crate) fn gen_file_group_ir<'db, 'ink>(
);

let fn_sig = f.ty(code_gen.db).callable_sig(code_gen.db).unwrap();
if !f.data(code_gen.db).visibility().is_private()
if f.visibility(code_gen.db).is_externally_visible()
&& !fn_sig.marshallable(code_gen.db)
{
intrinsics::collect_wrapper_body(
Expand All @@ -62,9 +64,10 @@ pub(crate) fn gen_file_group_ir<'db, 'ink>(
);
}
}
ModuleDef::Module(_) => (),
ModuleDef::Function(_) => (), // TODO: Extern types?
ModuleDef::Struct(_) => (),
ModuleDef::BuiltinType(_) => (),
ModuleDef::PrimitiveType(_) => (),
ModuleDef::TypeAlias(_) => (),
}
}
Expand All @@ -78,9 +81,9 @@ pub(crate) fn gen_file_group_ir<'db, 'ink>(
&intrinsics_map,
&code_gen.hir_types,
);
for def in code_gen.db.module_data(file_id).definitions() {
for def in module.declarations(code_gen.db) {
if let ModuleDef::Function(f) = def {
if !f.data(code_gen.db).visibility().is_private() && !f.is_extern(code_gen.db) {
if f.visibility(code_gen.db).is_externally_visible() && !f.is_extern(code_gen.db) {
let body = f.body(code_gen.db);
let infer = f.infer(code_gen.db);
dispatch_table_builder.collect_body(&body, &infer);
Expand Down Expand Up @@ -111,15 +114,15 @@ pub(crate) fn gen_file_group_ir<'db, 'ink>(
);

// Collect all used types
for def in code_gen.db.module_data(file_id).definitions() {
for def in module.declarations(code_gen.db) {
match def {
ModuleDef::Struct(s) => {
type_table_builder.collect_struct(*s);
type_table_builder.collect_struct(s);
}
ModuleDef::Function(f) => {
type_table_builder.collect_fn(*f);
type_table_builder.collect_fn(f);
}
ModuleDef::BuiltinType(_) | ModuleDef::TypeAlias(_) => (),
ModuleDef::PrimitiveType(_) | ModuleDef::TypeAlias(_) | ModuleDef::Module(_) => (),
}
}

Expand Down
13 changes: 5 additions & 8 deletions crates/mun_codegen/src/ir/intrinsics.rs
Expand Up @@ -2,7 +2,7 @@ use crate::{
intrinsics::{self, Intrinsic},
ir::dispatch_table::FunctionPrototype,
};
use hir::{Body, Expr, ExprId, HirDatabase, InferenceResult};
use hir::{Body, Expr, ExprId, HirDatabase, InferenceResult, ValueNs};
use inkwell::{context::Context, targets::TargetData, types::FunctionType};
use std::{collections::BTreeMap, sync::Arc};

Expand Down Expand Up @@ -56,13 +56,10 @@ fn collect_expr<'db, 'ink>(
}

if let Expr::Path(path) = expr {
let resolver = hir::resolver_for_expr(body.clone(), db, expr_id);
let resolution = resolver
.resolve_path_without_assoc_items(db, path)
.take_values()
.expect("unknown path");

if let hir::Resolution::Def(hir::ModuleDef::Struct(_)) = resolution {
let resolver = hir::resolver_for_expr(db.upcast(), body.owner(), expr_id);
if let Some((ValueNs::StructId(_), _)) =
resolver.resolve_path_as_value_fully(db.upcast(), path)
{
collect_intrinsic(context, &target, &intrinsics::new, intrinsics);
// self.collect_intrinsic( module, entries, &intrinsics::drop);
*needs_alloc = true;
Expand Down

0 comments on commit a45496a

Please sign in to comment.