/* Odin Middle End Notation "me" prefix means middle end */ struct meModule; // Build/Translation Unit struct meValue; struct meProcedure; struct meBlock; struct meInstruction; struct meConstant; struct meGlobalVariable; struct meParameter; enum meValueKind : u8 { meValue_Invalid = 0, meValue_Instruction, meValue_ConstantValue, meValue_Block, meValue_Procedure, meValue_GlobalVariable, meValue_Parameter, }; struct meValue { meValueKind kind; union { meInstruction *instr; meConstant *constant; meBlock *block; meProcedure *proc; meGlobalVariable *global; meParameter *param; }; }; enum meOpKind : u8 { meOp_Invalid = 0, meOp_Unreachable, meOp_Return, meOp_Jump, meOp_CondJump, meOp_Switch, meOp_Phi, // Unary Operators meOp_Neg, meOp_LogicalNot, meOp_BitwiseNot, // Binary Arithmetic Operators meOp_Add, meOp_Sub, meOp_Mul, meOp_Div, meOp_Rem, // Binary Bitwise Operators meOp_Shl, meOp_LShr, meOp_AShr, meOp_And, meOp_Or, meOp_Xor, // Memory Operators meOp_Alloca, meOp_Load, meOp_Store, meOp_UnalignedLoad, meOp_UnalignedStore, meOp_GetElementPtr, meOp_PtrOffset, meOp_PtrSub, // Cast Operators meOp_Cast, meOp_Transmute, // Binary Comparison Operators meOp_Eq, meOp_NotEq, meOp_Lt, meOp_LtEq, meOp_Gt, meOp_GtEq, meOp_Min, meOp_Max, // Ternary Operators meOp_Select, // Other meOp_Call, meOp_BuiltinCall, meOp_ExtractValue, meOp_Swizzle, meOp_Alias, // alias of another value // Atomics meOp_Fence, meOp_AtomicXchg, meOp_AtomicCmpXchg, }; enum meInstructionFlags : u16 { meInstructionFlag_Volatile = 1<<0, meInstructionFlag_AtomicRMW = 1<<1, meInstructionFlag_ForceInline = 1<<2, meInstructionFlag_ForceNoInline = 1<<3, meInstructionFlag_HasSideEffects = 1<<4, }; enum meAtomicOrderingKind : u8 { meAtomicOrdering_NotAtomic, meAtomicOrdering_Unordered, meAtomicOrdering_Monotonic, meAtomicOrdering_Acquire, meAtomicOrdering_Release, meAtomicOrdering_AcquireRelease, meAtomicOrdering_SequentiallyConsistent, meAtomicOrdering_COUNT, }; enum meLinkageKind : u8 { meLinkage_Strong, meLinkage_Weak, meLinkage_Internal, meLinkage_LinkOnce, meLinkage_Export, }; enum {me_INSTRUCTION_MAX_ARG_COUNT = 4}; struct meInstruction { meOpKind op; meAtomicOrderingKind atomic_ordering; u16 flags; u16 alignment; u16 uses; Type * type; meProcedure *parent; TokenPos pos; meValue ops[me_INSTRUCTION_MAX_ARG_COUNT]; isize op_count; Slice *extra_ops; // non-null if used }; struct meConstant { ExactValue value; Type *type; }; struct meBlock { meProcedure * parent; String name; Array instructions; Scope * scope; i32 scope_index; Array preds; Array succs; }; struct meBranchBlocks { Ast *label; meBlock *break_; meBlock *continue_; }; struct meTargetList { meTargetList *prev; bool is_block; meBlock *break_; meBlock *continue_; meBlock *fallthrough_; }; enum meGlobalVariableFlags : u16 { meGlobalVariableFlag_ThreadLocal_default = 1<<0, meGlobalVariableFlag_ThreadLocal_localdynamic = 1<<1, meGlobalVariableFlag_ThreadLocal_initialexec = 1<<2, meGlobalVariableFlag_ThreadLocal_localexec = 1<<3, }; struct meGlobalVariable { meModule * module; Entity * entity; Type * type; String name; // link name meLinkageKind linkage; u16 flags; ExactValue value; i32 uses; DeclInfo * decl; }; struct meParameter { String name; Entity * entity; meProcedure *parent; i32 uses; }; enum meAddrKind : u32 { meAddr_Default = 0, meAddr_Map, meAddr_Context, meAddr_SoaVariable, meAddr_RelativePointer, meAddr_RelativeSlice, meAddr_Swizzle, meAddr_SwizzleLarge, }; struct meAddr { meAddrKind kind; meValue addr; union { struct { meValue key; Type *type; Type *result; } map; struct { Selection sel; } ctx; struct { meValue index; Ast *index_expr; } soa; struct { meValue index; Ast *node; } index_set; struct { bool deref; } relative; struct { Type *type; u8 count; // 2, 3, or 4 components u8 indices[4]; } swizzle; struct { Type *type; Slice indices; } swizzle_large; }; }; struct meContextData { meAddr ctx; i32 scope_index; i32 uses; }; enum meDeferKind { meDefer_Node, meDefer_Proc, }; struct meDefer { meDeferKind kind; i32 scope_index; i32 context_stack_count; meBlock * block; union { Ast *stmt; struct { meValue deferred; Array result_as_args; } proc; }; }; enum meDeferExitKind { meDeferExit_Default, meDeferExit_Return, meDeferExit_Branch, }; enum meProcedureFlags : u32 { meProcedureFlag_Foreign = 1<<1, meProcedureFlag_Export = 1<<2, meProcedureFlag_EntryPoint = 1<<3, meProcedureFlag_Startup = 1<<4, meProcedureFlag_Inline = 1<<5, meProcedureFlag_NoInline = 1<<6, meProcedureFlag_Cold = 1<<7, meProcedureFlag_Hot = 1<<8, meProcedureFlag_WithoutMemcpy = 1<<9, }; struct meProcedure { meModule * module; Entity * entity; Type * type; String name; // link name meLinkageKind linkage; u32 flags; i32 uses; BuiltinProcId builtin_id; u16 state_flags; bool is_done; meProcedure * parent; Array children; Ast *type_expr; Ast *body; u64 tags; meAddr return_ptr; Array defer_stmts; Array blocks; meBlock * decl_block; meBlock * entry_block; meBlock * curr_block; Array branch_blocks; Scope *curr_scope; i32 scope_index; meTargetList *target_list; Ast *curr_stmt; Array scope_stack; Array context_stack; }; struct meModule { // Build/Translation Unit CheckerInfo *info; AstPackage *pkg; // associated PtrMap values; PtrMap soa_values; StringMap members; StringMap procedures; PtrMap procedure_values; Array missing_procedures_to_check; StringMap const_strings; PtrMap equal_procs; PtrMap hasher_procs; u32 nested_type_name_guid; Array procedures_to_generate; Array foreign_library_paths; meProcedure *curr_procedure; StringMap objc_classes; StringMap objc_selectors; }; bool me_generate(Checker *c); String me_get_entity_name(meModule *m, Entity *e, String default_name = {}); meProcedure *me_procedure_create(meModule *m, Entity *entity, bool ignore_body=false); meValue me_value(meInstruction *instr); meValue me_value(meConstant *constant); meValue me_value(meBlock *block); meValue me_value(meProcedure *proc); meValue me_value(meGlobalVariable *global); meValue me_value(meParameter *param); void me_build_stmt(meProcedure *p, Ast *stmt); meValue me_build_expr(meProcedure *p, Ast *expr); meValue me_emit_conv(meProcedure *p, meValue value, Type *type);