1
0
forked from M-Labs/nac3

meta: Bringup some documentation

This commit is contained in:
David Mak 2023-10-18 13:40:37 +08:00
parent d304afd333
commit a1f244834f
4 changed files with 71 additions and 11 deletions

View File

@ -265,12 +265,12 @@ impl InnerResolver {
Ok(Ok(ty)) Ok(Ok(ty))
} }
/// handle python objects that represent types themselves /// Handles python objects that represent types themselves,
/// ///
/// primitives and class types should be themselves, use `ty_id` to check, /// Primitives and class types should be themselves, use `ty_id` to check;
/// TypeVars and GenericAlias(`A[int, bool]`) should use `ty_ty_id` to check /// TypeVars and GenericAlias(`A[int, bool]`) should use `ty_ty_id` to check.
/// ///
/// the `bool` value returned indicates whether they are instantiated or not /// The `bool` value returned indicates whether they are instantiated or not
fn get_pyty_obj_type( fn get_pyty_obj_type(
&self, &self,
py: Python, py: Python,

View File

@ -226,10 +226,13 @@ impl DefaultCodeGenerator {
} }
impl CodeGenerator for DefaultCodeGenerator { impl CodeGenerator for DefaultCodeGenerator {
/// Returns the name for this [CodeGenerator].
fn get_name(&self) -> &str { fn get_name(&self) -> &str {
&self.name &self.name
} }
/// Returns an LLVM integer type representing `size_t`.
fn get_size_type<'ctx>(&self, ctx: &'ctx Context) -> IntType<'ctx> { fn get_size_type<'ctx>(&self, ctx: &'ctx Context) -> IntType<'ctx> {
// it should be unsigned, but we don't really need unsigned and this could save us from // it should be unsigned, but we don't really need unsigned and this could save us from
// having to do a bit cast... // having to do a bit cast...

View File

@ -126,42 +126,74 @@ impl CodeGenTargetMachineOptions {
} }
pub struct CodeGenContext<'ctx, 'a> { pub struct CodeGenContext<'ctx, 'a> {
/// The LLVM context associated with [this context][CodeGenContext].
pub ctx: &'ctx Context, pub ctx: &'ctx Context,
/// The [Builder] instance for creating LLVM IR statements.
pub builder: Builder<'ctx>, pub builder: Builder<'ctx>,
/// The [DebugInfoBuilder], [compilation unit information][DICompileUnit], and /// The [DebugInfoBuilder], [compilation unit information][DICompileUnit], and
/// [scope information][DIScope] of this context. /// [scope information][DIScope] of this context.
pub debug_info: (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>, DIScope<'ctx>), pub debug_info: (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>, DIScope<'ctx>),
/// The module for which [this context][CodeGenContext] is generating into.
pub module: Module<'ctx>, pub module: Module<'ctx>,
/// The [TopLevelContext] associated with [this context][CodeGenContext].
pub top_level: &'a TopLevelContext, pub top_level: &'a TopLevelContext,
pub unifier: Unifier, pub unifier: Unifier,
pub resolver: Arc<dyn SymbolResolver + Send + Sync>, pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
pub static_value_store: Arc<Mutex<StaticValueStore>>, pub static_value_store: Arc<Mutex<StaticValueStore>>,
/// A [HashMap] containing the mapping between the names of variables currently in-scope and
/// its value information.
pub var_assignment: HashMap<StrRef, VarValue<'ctx>>, pub var_assignment: HashMap<StrRef, VarValue<'ctx>>,
///
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>, pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
pub primitives: PrimitiveStore, pub primitives: PrimitiveStore,
pub calls: Arc<HashMap<CodeLocation, CallId>>, pub calls: Arc<HashMap<CodeLocation, CallId>>,
pub registry: &'a WorkerRegistry, pub registry: &'a WorkerRegistry,
// const string cache
/// Cache for constant strings.
pub const_strings: HashMap<String, BasicValueEnum<'ctx>>, pub const_strings: HashMap<String, BasicValueEnum<'ctx>>,
// stores the alloca for variables
/// [BasicBlock] containing all `alloca` statements for the current function.
pub init_bb: BasicBlock<'ctx>, pub init_bb: BasicBlock<'ctx>,
pub exception_val: Option<PointerValue<'ctx>>, pub exception_val: Option<PointerValue<'ctx>>,
/// The header and exit basic blocks of a loop in this context. See /// The header and exit basic blocks of a loop in this context. See
/// https://llvm.org/docs/LoopTerminology.html for explanation of these terminology. /// https://llvm.org/docs/LoopTerminology.html for explanation of these terminology.
pub loop_target: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>, pub loop_target: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>,
// unwind target bb
/// The target [BasicBlock] to jump to when performing stack unwind.
pub unwind_target: Option<BasicBlock<'ctx>>, pub unwind_target: Option<BasicBlock<'ctx>>,
// return target bb, just emit ret if no such target
/// The target [BasicBlock] to jump to before returning from the function.
///
/// If this field is [None] when generating a return from a function, `ret` with no argument can
/// be emitted.
pub return_target: Option<BasicBlock<'ctx>>, pub return_target: Option<BasicBlock<'ctx>>,
/// The [PointerValue] containing the return value of the function.
pub return_buffer: Option<PointerValue<'ctx>>, pub return_buffer: Option<PointerValue<'ctx>>,
// outer catch clauses // outer catch clauses
pub outer_catch_clauses: pub outer_catch_clauses:
Option<(Vec<Option<BasicValueEnum<'ctx>>>, BasicBlock<'ctx>, PhiValue<'ctx>)>, Option<(Vec<Option<BasicValueEnum<'ctx>>>, BasicBlock<'ctx>, PhiValue<'ctx>)>,
/// Whether `sret` is needed for the first parameter of the function.
///
/// See [need_sret].
pub need_sret: bool, pub need_sret: bool,
/// The current source location.
pub current_loc: Location, pub current_loc: Location,
} }
impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
/// Whether the [current basic block][Builder::get_insert_block] referenced by `builder`
/// contains a [terminator statement][BasicBlock::get_terminator].
pub fn is_terminated(&self) -> bool { pub fn is_terminated(&self) -> bool {
self.builder.get_insert_block().and_then(|bb| bb.get_terminator()).is_some() self.builder.get_insert_block().and_then(|bb| bb.get_terminator()).is_some()
} }
@ -186,17 +218,26 @@ impl WithCall {
pub struct WorkerRegistry { pub struct WorkerRegistry {
sender: Arc<Sender<Option<CodeGenTask>>>, sender: Arc<Sender<Option<CodeGenTask>>>,
receiver: Arc<Receiver<Option<CodeGenTask>>>, receiver: Arc<Receiver<Option<CodeGenTask>>>,
/// Whether any thread in this registry has panicked.
panicked: AtomicBool, panicked: AtomicBool,
/// The total number of tasks queued or completed in the registry.
task_count: Mutex<usize>, task_count: Mutex<usize>,
/// The number of threads available for this registry.
thread_count: usize, thread_count: usize,
wait_condvar: Condvar, wait_condvar: Condvar,
top_level_ctx: Arc<TopLevelContext>, top_level_ctx: Arc<TopLevelContext>,
static_value_store: Arc<Mutex<StaticValueStore>>, static_value_store: Arc<Mutex<StaticValueStore>>,
/// LLVM-related options for code generation. /// LLVM-related options for code generation.
llvm_options: CodeGenLLVMOptions, llvm_options: CodeGenLLVMOptions,
} }
impl WorkerRegistry { impl WorkerRegistry {
/// Creates workers for this registry.
pub fn create_workers<G: CodeGenerator + Send + 'static>( pub fn create_workers<G: CodeGenerator + Send + 'static>(
generators: Vec<Box<G>>, generators: Vec<Box<G>>,
top_level_ctx: Arc<TopLevelContext>, top_level_ctx: Arc<TopLevelContext>,
@ -278,11 +319,13 @@ impl WorkerRegistry {
} }
} }
/// Adds a task to this [WorkerRegistry].
pub fn add_task(&self, task: CodeGenTask) { pub fn add_task(&self, task: CodeGenTask) {
*self.task_count.lock() += 1; *self.task_count.lock() += 1;
self.sender.send(Some(task)).unwrap(); self.sender.send(Some(task)).unwrap();
} }
/// Function executed by worker thread for generating IR for each function.
fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, f: Arc<WithCall>) { fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, f: Arc<WithCall>) {
let context = Context::create(); let context = Context::create();
let mut builder = context.create_builder(); let mut builder = context.create_builder();
@ -502,6 +545,14 @@ fn get_llvm_abi_type<'ctx>(
} }
} }
/// Whether `sret` is needed for a return value with type `ty`.
///
/// When returning a large data structure (e.g. structures that do not fit in 1-2 native words of
/// the target processor) by value, a synthetic parameter with a pointer type will be passed in the
/// slot of the first parameter to act as the location of which the return value is passed into.
///
/// See [https://releases.llvm.org/14.0.0/docs/LangRef.html#parameter-attributes] for more
/// information.
fn need_sret(ty: BasicTypeEnum) -> bool { fn need_sret(ty: BasicTypeEnum) -> bool {
fn need_sret_impl(ty: BasicTypeEnum, maybe_large: bool) -> bool { fn need_sret_impl(ty: BasicTypeEnum, maybe_large: bool) -> bool {
match ty { match ty {

View File

@ -205,6 +205,7 @@ pub trait StaticValue {
/// Returns a unique identifier for this value. /// Returns a unique identifier for this value.
fn get_unique_identifier(&self) -> u64; fn get_unique_identifier(&self) -> u64;
/// Returns the constant object represented by this unique identifier.
fn get_const_obj<'ctx>( fn get_const_obj<'ctx>(
&self, &self,
ctx: &mut CodeGenContext<'ctx, '_>, ctx: &mut CodeGenContext<'ctx, '_>,
@ -232,7 +233,10 @@ pub trait StaticValue {
#[derive(Clone)] #[derive(Clone)]
pub enum ValueEnum<'ctx> { pub enum ValueEnum<'ctx> {
/// [ValueEnum] representing a static value.
Static(Arc<dyn StaticValue + Send + Sync>), Static(Arc<dyn StaticValue + Send + Sync>),
/// [ValueEnum] representing a dynamic value.
Dynamic(BasicValueEnum<'ctx>), Dynamic(BasicValueEnum<'ctx>),
} }
@ -267,6 +271,8 @@ impl<'ctx> From<StructValue<'ctx>> for ValueEnum<'ctx> {
} }
impl<'ctx> ValueEnum<'ctx> { impl<'ctx> ValueEnum<'ctx> {
/// Converts this [ValueEnum] to a [BasicValueEnum].
pub fn to_basic_value_enum<'a>( pub fn to_basic_value_enum<'a>(
self, self,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
@ -281,7 +287,7 @@ impl<'ctx> ValueEnum<'ctx> {
} }
pub trait SymbolResolver { pub trait SymbolResolver {
// get type of type variable identifier or top-level function type /// Get type of type variable identifier or top-level function type,
fn get_symbol_type( fn get_symbol_type(
&self, &self,
unifier: &mut Unifier, unifier: &mut Unifier,
@ -290,7 +296,7 @@ pub trait SymbolResolver {
str: StrRef, str: StrRef,
) -> Result<Type, String>; ) -> Result<Type, String>;
// get the top-level definition of identifiers /// Get the top-level definition of identifiers.
fn get_identifier_def(&self, str: StrRef) -> Result<DefinitionId, String>; fn get_identifier_def(&self, str: StrRef) -> Result<DefinitionId, String>;
fn get_symbol_value<'ctx>( fn get_symbol_value<'ctx>(
@ -329,7 +335,7 @@ thread_local! {
]; ];
} }
// convert type annotation into type /// Converts a type annotation into a [Type].
pub fn parse_type_annotation<T>( pub fn parse_type_annotation<T>(
resolver: &dyn SymbolResolver, resolver: &dyn SymbolResolver,
top_level_defs: &[Arc<RwLock<TopLevelDef>>], top_level_defs: &[Arc<RwLock<TopLevelDef>>],