package ir import "../source" import "../symbol" import "../target" import "../types" import "core:mem" Instruction_Id :: distinct u32 Local_Id :: distinct u32 Function_Id :: distinct u32 Global_Id :: distinct u32 Ref :: distinct u32 INVALID_INSTRUCTION :: Instruction_Id(0xffff_ffff) INVALID_LOCAL :: Local_Id(0xffff_ffff) INVALID_FUNCTION :: Function_Id(0xffff_ffff) INVALID_GLOBAL :: Global_Id(0xffff_ffff) INVALID_REF :: Ref(0xffff_ffff) instruction_id :: proc(index: int) -> Instruction_Id { assert(index >= 0 && u64(index) < u64(INVALID_INSTRUCTION)) return Instruction_Id(index) } local_id :: proc(index: int) -> Local_Id { assert(index >= 0 && u64(index) < u64(INVALID_LOCAL)) return Local_Id(index) } function_id :: proc(index: int) -> Function_Id { assert(index >= 0 && u64(index) < u64(INVALID_FUNCTION)) return Function_Id(index) } global_id :: proc(index: int) -> Global_Id { assert(index >= 0 && u64(index) < u64(INVALID_GLOBAL)) return Global_Id(index) } index :: proc(id: $T, invalid: T, count: int) -> (int, bool) { value := int(id) return value, id != invalid && value < count } local_ref :: proc(id: Local_Id) -> Ref {return Ref(id)} function_ref :: proc(id: Function_Id) -> Ref {return Ref(id)} global_ref :: proc(id: Global_Id) -> Ref {return Ref(id)} as_local :: proc(ref: Ref) -> Local_Id {return Local_Id(ref)} as_function :: proc(ref: Ref) -> Function_Id {return Function_Id(ref)} as_global :: proc(ref: Ref) -> Global_Id {return Global_Id(ref)} Calling_Convention :: enum u8 { Brolang, C, } Implementation :: enum u8 { Definition, Declaration, } Linkage :: enum u8 { Internal, External, } Opcode :: enum u8 { Param, Const, String, Aggregate, None, Optional_Some, Load_Global, Function_Address, Address_Global, Address_Of, Alloca, Index_Address, Field_Address, Load, Store, Slice, Length, Slice_Ptr, Unwrap, Optional_Is_Some, Optional_Value, Orelse_Begin, Orelse, Widen, C_Vararg_Promote, Weaken_Pointer, Weaken_Slice, Decay_Array_Pointer, Neg_Checked, Add_Checked, Pointer_Add, Not, Compare, Label, Br, Cond_Br, Call, Trap, Return, Return_Void, } // Compare_Predicate is stored in Instruction.integer for the Compare opcode. Compare_Predicate :: enum u8 { Eq, Ne, Lt, Le, Gt, Ge, } Instruction :: struct { span: source.Span, type: types.Type, integer: i64, args: []Instruction_Id, target: Ref, a: Instruction_Id, b: Instruction_Id, diagnostic: source.Diagnostic_Id, op: Opcode, } Function :: struct { link_name: string, calling_convention: Calling_Convention, implementation: Implementation, linkage: Linkage, is_main: bool, variadic: bool, param_types: []types.Type, result: types.Type, instructions: []Instruction, problematic: bool, } Global :: struct { name: symbol.Id, link_name: string, type: types.Type, is_static: bool, external: bool, writable: bool, static_value: i64, initializer: []Instruction, problematic: bool, diagnostic: source.Diagnostic_Id, } Module :: struct { functions: [dynamic]Function, globals: [dynamic]Global, strings: [dynamic]string, types: types.Store, target: target.Target, allocator: mem.Allocator, } init_module :: proc(selected := target.DEFAULT, allocator := context.allocator) -> Module { module: Module module.target = selected module.types = types.init_store(allocator) module.types.selected = selected module.functions.allocator = allocator module.globals.allocator = allocator module.strings.allocator = allocator module.allocator = allocator return module } destroy_instructions :: proc(instructions: []Instruction, allocator: mem.Allocator) { for instruction in instructions { delete(instruction.args, allocator) } delete(instructions, allocator) } destroy_module :: proc(module: ^Module) { for function in module.functions { delete(function.link_name, module.allocator) delete(function.param_types, module.allocator) destroy_instructions(function.instructions, module.allocator) } for global in module.globals { delete(global.link_name, module.allocator) destroy_instructions(global.initializer, module.allocator) } for value in module.strings { delete(value, module.allocator) } delete(module.functions) delete(module.globals) delete(module.strings) types.destroy_store(&module.types) }