// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

namespace PackageFormat;

file_identifier "CHIR";

// Using 'uint32' as type of 'Type/Value/Expression/CustomTypeDef' 's table index.
// 0 is invalid index, valid index start from 1, which is the offset of table plus 1.
enum CHIRTypeKind: int16 {
	INVALID,
	// integer
	INT8,
	INT16,
	INT32,
	INT64,
	INT_NATIVE,
	// unsigned integer
	UINT8,
	UINT16,
	UINT32,
	UINT64,
	UINT_NATIVE,
	// float
	FLOAT16,
	FLOAT32,
	FLOAT64,
	// other primitive type
	RUNE,
	BOOLEAN,
	UNIT,
	NOTHING,
	// Void type
	VOID,
	// composite type
	TUPLE,
	CLOSURE,
	STRUCT,
	ENUM,
	FUNC,
	CLASS,
	// Built-in array related type
	RAWARRAY,
	VARRAY,
	// Built-in CFFI related type
	C_POINTER,
	C_STRING,
	// Generic type
	GENERIC,
	// Referece to an value with abritray type
	REFTYPE,
}

enum SourceExpr: int8 {
    IF_EXPR,
    WHILE_EXPR,
    DO_WHILE_EXPR,
    MATCH_EXPR,
    IF_LET_OR_WHILE_LET,
    QUEST,
    BINARY,
    FOR_IN_EXPR,
    OTHER
}

table Type {
kind: CHIRTypeKind;
typeID: uint32;
argTys: [uint32]; // use typeID
refDims: uint64 = 0;
}

table RuneType {
base: Type;
}

table BooleanType {
base: Type;
}

table UnitType {
base: Type;
}

table NothingType {
base: Type;
}

table NumericType {
base: Type;
}

table IntType {
base: NumericType;
}

table FloatType {
base: NumericType;
}

table TupleType {
base: Type;
}

table ClosureType {
base: Type;
}

table RawArrayType {
base: Type;
dims: uint64;
}

table VArrayType {
base: Type;
size: int64;
}

table FuncType {
base: Type;
isCFuncType: bool;
hasVarArg: bool;
}

table CustomType {
base: Type;
customTypeDef: uint32; // use customTypeDefID
}

table EnumType {
base: CustomType;
isBoxed: bool;
}

table StructType {
base: CustomType;
}

table ClassType {
base: CustomType;
}

table CStringType {
base: Type;
}

table CPointerType {
base: Type;
}

table GenericType {
base: Type;
identifier: string;
upperBounds: [uint32]; // use typeID
}

table RefType {
base: Type;
}

table BoxType {
base: Type;
}

table VoidType {
base: Type;
}

enum Linkage: int16 {
  WEAK_ODR,
  EXTERNAL,
  INTERNAL,
  LINKONCE_ODR,
  EXTERNAL_WEAK,
}

table Pos {
line: uint64;
column: uint64;
}

table DebugLocation {
filePath: string;
fileId: uint32;
beginPos: Pos;
endPos: Pos;
scope: [int32];
}

table LinkTypeInfo {
    linkage: Linkage;
}

enum SkipKind : uint8 {
    NO_SKIP,
    SKIP_DCE_WARNING,
    SKIP_CODEGEN,
}

table SkipCheck {
    skipKind: SkipKind;
}

table NeedCheckArrayBound {
    need: bool;
}

table NeedCheckCast {
    need: bool;
}

enum OverflowStrategy: int16 {
	NA,
	CHECKED,
	WRAPPING,
	THROWING,
	SATURATING
}

enum Inline: int8 {
    ALWAYS, NEVER, DEFAULT
}

table InlineInfo {
    kind: Inline;
}

table NeverOverflowInfo {
    neverOverflow: bool;
}

union Annotation {
needCheckArrayBound: NeedCheckArrayBound,
needCheckCast: NeedCheckCast,
debugLocationInfo: DebugLocation,
debugLocationInfoForWarning: DebugLocation,
linkTypeInfo: LinkTypeInfo,
skipCheck: SkipCheck,
inlineInfo: InlineInfo,
neverOverflowInfo: NeverOverflowInfo,
}

table Base {
    annos: [Annotation];
}

enum ValueKind: int16 {
	LITERAL,
	GLOBALVAR,
	PARAMETER,
	IMPORTED_FUNC,
	IMPORTED_VAR,
	LOCALVAR,
	FUNC,
	BLOCK,
	BLOCK_GROUP
}

table Value {
base: Base;
type: uint32; // use typeID
identifier: string;
kind: ValueKind;
valueID: uint32;
users: [uint32]; // use expressionID
attributes: uint64;
}

enum ConstantValueKind: int16 {
	BOOL,
	RUNE,
	INT,
	FLOAT,
	STRING,
	UNIT,
	NULL,
	FUNC
}

table LiteralValue {
base: Value;
literalKind: ConstantValueKind;
}

table BoolLiteral {
base: LiteralValue;
val: bool;
}

table StringLiteral {
base: LiteralValue;
val: string;
isJString: bool;
}

table RuneLiteral {
base: LiteralValue;
val: uint64; // coding of `rune`
}

table IntLiteral {
base: LiteralValue;
val: uint64;
}

table FloatLiteral {
base: LiteralValue;
val: double;
}

table UnitLiteral {
base: LiteralValue;
}

table NullLiteral {
base: LiteralValue;
}

table Parameter {
base: Value;
ownedFunc: uint32;  // use valueID
ownedLambda: uint32;  // use expressionID
associatedDebug: uint32;  // use expressionID
annoInfo: AnnoInfo;
}

table LocalVar {
base: Value;
associatedExpr: uint32; // use expressionID
isRetVal: bool = false;
debug: uint32; // use expressionID(Debug)
accurateEnvObjTy: uint32; // use typeID
}

table GlobalVar {
base: Value;
rawMangledName: string;
srcCodeIdentifier: string;
packageName: string;
defaultInitVal: uint32; // use valueID
associatedInitFunc: uint32; // use valueID
declaredParent: uint32; // use customTypeDefID
annoInfo: AnnoInfo;
}

enum ImportedValueKind: int16 {
	VARIABLE,
	FUNC
}

enum FuncKind: int16 {
	DEFAULT,
	GETTER,
	SETTER,
    LAMBDA,
	CLASS_CONSTRUCTOR,
	PRIMAL_CLASS_CONSTRUCTOR,
	STRUCT_CONSTRUCTOR,
	PRIMAL_STRUCT_CONSTRUCTOR,
	GLOBALVAR_INIT,
	FINALIZER,
	MAIN_ENTRY,
	ANNOFACTORY_FUNC,
	MACRO_FUNC,
    MACRO_INVOKE_FUNC,
    DEFAULT_PARAMETER_FUNC
}

table ImportedValue {
base: Value;
packageName: string;
}

table ImportedFunc {
base: ImportedValue;
srcCodeIdentifier: string;
funcKind: FuncKind;
genericTypeParams: [uint32];  // use typeID
implicitedImported: bool;
ownerFunc: uint32;  // use valueID
rawMangledName: string;
packageName: string;
paramInfo: [AbstractMethodParam];
declaredParent: uint32; // use customTypeDefID
extendedParent: uint32; // use customTypeDefID
genericDecl: uint32; // use valueID
annoInfo: AnnoInfo;
isFastNative: bool;
isCFFIWrapper: bool;
}

table ImportedVar {
base: ImportedValue;
srcCodeIdentifier: string;
annoInfo: AnnoInfo;
}

table Block {
base: Value;
parentGroup: uint32; // use valueID
exprs: [uint32];  // use expressionID
predecessors: [uint32];  // use valueID
isLandingPadBlock: bool;
exceptionCatchList: [uint32];  // use typeID
predecessorTerminal: uint32; // use expressionID (Terminator)
}

table BlockGroup {
base: Value;
entryBlock: uint32;  // use valueID
blocks: [uint32];  // use valueID
ownedFunc: uint32;  // use valueID
ownedLambda: uint32;  // use expressionID
}

table Func {
base: Value;
srcCodeIdentifier: string;
packageName: string;
body: uint32; // use valueID
params: [uint32]; // use valueID
funcKind: FuncKind;
genericTypeParams: [uint32]; // use typeID
retVal: uint32; // use valueID
rawMangledName: string;
declaredParent: uint32; // use customTypeDefID
extendedParent: uint32; // use customTypeDefID
genericDecl: uint32; // use valueID
annoInfo: AnnoInfo;
parentName: string;
propLoc: DebugLocation;
isFastNative: bool;
isCFFIWrapper: bool;
ownerFunc: uint32; // use valueID
}

enum CustomTypeKind: int16 {
	STRUCT,
	ENUM,
	CLASS
}

table AnnoInfo {
mangledName: string;
}

table MemberVarInfo {
name: string;
rawMangledName: string;
type: uint32; // use typeID
attributes: uint64;
loc: DebugLocation;
annoInfo : AnnoInfo;
}

table CustomTypeDef {
base: Base;
kind: CustomTypeKind;
identifier: string;
srcCodeIdentifier: string;
packageName: string;
customTypeDefID: uint32;
type: uint32; // use typeID
genericTypeParams: [uint32]; // use typeID
methods: [uint32]; // use valueID
instanceMemberVars: [MemberVarInfo];
staticMemberVars: [uint32]; // use valueID
attributes: uint64;
implementedInterfaces: [uint32]; // use customTypeDefID
extendedInterfaces: [uint32]; // use customTypeDefID
extendedMethods: [uint32]; // use valueID
genericDecl: uint32;  // use customTypeDefID
annoInfo: AnnoInfo;
}

table EnumCtorInfo {
identifier: string;
mangledName: string;
funcType: uint32; // use typeID
}

table EnumDef {
base: CustomTypeDef;
ctors: [EnumCtorInfo];
nonExhaustive: bool;
}

table StructDef {
base: CustomTypeDef;
isCStruct: bool;
}

enum ClassDefKind: int16 {
	CLASS,
	INTERFACE
}

table AbstractMethodParam {
paramName: string;
paramType: uint32; // use typeID
annoInfo : AnnoInfo;
}

table VTableElement {
virtualMethodName: string;
virtualMethodType: uint32; // use typeID
dispatchedFunc: uint32; // use valueID
}

table AbstractMethodInfo {
methodName: string;
mangledName: string;
methodType: uint32; // use typeID
paramsInfo: [AbstractMethodParam];
attributes: uint64;
annoInfo : AnnoInfo;
}

table ClassDef {
base: CustomTypeDef;
kind: ClassDefKind;
isAnnotation: bool = false;
isJavaClass: bool = false;
superClass: uint32; // use customTypeDefID
finalizer: uint32; // use valueID
vtable: [VTableElement];
abstractMethods: [AbstractMethodInfo];
isVtableMerged: bool;
isBoxedByCC: bool;
}

enum CHIRExprKind: int16 {
	INVALID,
	// Terminator
	GOTO,
	BRANCH,
	MULTIBRANCH,
	EXIT,
	APPLY_WITH_EXCEPTION,
	INVOKE_WITH_EXCEPTION,
	RAISE_EXCEPTION,
	INT_OP_WITH_EXCEPTION,
	SPAWN_WITH_EXCEPTION,
	TYPECAST_WITH_EXCEPTION,
	INTRINSIC_WITH_EXCEPTION,
	ALLOCATE_WITH_EXCEPTION,
	RAW_ARRAY_ALLOCATE_WITH_EXCEPTION,
	RAW_ARRAY_LITERAL_ALLOCATE_WITH_EXCEPTION,
	// Unary
	NEG,
	NOT,
	BITNOT,
	// Binary
	ADD,
	SUB,
	MUL,
	DIV,
	MOD,
	EXP,
	LSHIFT,
	RSHIFT,
	BITAND,
	BITOR,
	BITXOR,
	LT,
	GT,
	LE,
	GE,
	EQUAL,
	NOTEQUAL,
	AND,
	OR,
	// Memory
	ALLOCATE,
	LOAD,
	STORE,
	GET_ELEMENT_REF,
	// Complext
	IF,
	LOOP,
	FORIN_RANGE,
    FORIN_ITER,
    FORIN_CLOSED_RANGE,
	LAMBDA,
	// Others
	CONSTANT,
	DEBUG,
	TUPLE,
	FIELD,
	APPLY,
	INVOKE,
	INVOKE_STATIC,
	INSTANCEOF,
	BOX,
	UNBOX,
	TYPECAST,
	GET_EXCEPTION,
	RAW_ARRAY_ALLOCATE,
	RAW_ARRAY_LITERAL_ALLOCATE,
	RAW_ARRAY_INIT_BY_VALUE,
	VARRAY,
	VARRAY_BUILDER,
	INTRINSIC,
	SPAWN
}

enum IntrinsicKind: int16 {
    NOT_INTRINSIC,
    NOT_IMPLEMENTED,

    // For hoisting, but we should later split arraybuilder
    // into allocation and initialisation
    ARRAY_INIT,

    // CORE
    SIZE_OF,
    ALIGN_OF,
    ARRAY_ACQUIRE_RAW_DATA,
    ARRAY_RELEASE_RAW_DATA,
    ARRAY_BUILT_IN_COPY_TO,
    ARRAY_GET,
    ARRAY_SET,
    ARRAY_GET_UNCHECKED,
    ARRAY_GET_REF_UNCHECKED,
    ARRAY_SET_UNCHECKED,
    ARRAY_SIZE,
    ARRAY_CLONE,
    ARRAY_SLICE_INIT,
    ARRAY_SLICE,
    ARRAY_SLICE_RAWARRAY,
    ARRAY_SLICE_START,
    ARRAY_SLICE_SIZE,
    ARRAY_SLICE_GET_ELEMENT,
    ARRAY_SLICE_SET_ELEMENT,
    FILL_IN_STACK_TRACE,
    DECODE_STACK_TRACE,

    CHR,
    ORD,

    CPOINTER_GET_POINTER_ADDRESS,
    CPOINTER_INIT0, // CPointer constructor with no arguments
    CPOINTER_INIT1, // CPointer constructor with one argument
    CPOINTER_READ,
    CPOINTER_WRITE,
    CPOINTER_ADD,

    CSTRING_INIT,
    CSTRING_CONVERT_CSTR_TO_PTR,

    INOUT_PARAM,

    REGISTER_WATCHED_OBJECT,

    OBJECT_REFEQ,

    RAW_ARRAY_REFEQ,  // cjnative only

    OBJECT_ZERO_VALUE,

    INVOKE_GC,
    SET_GC_THRESHOLD,
    GET_MAX_HEAP_SIZE,
    GET_ALLOCATE_HEAP_SIZE,
    DUMP_CJ_HEAP_DATA,
    GET_GC_COUNT,
    GET_GC_TIME_US,
    GET_GC_FREED_SIZE,
    START_CJ_CPU_PROFILING,
    STOP_CJ_CPU_PROFILING,
    GET_REAL_HEAP_SIZE,
    GET_THREAD_NUMBER,
    GET_BLOCKING_THREAD_NUMBER,
    GET_NATIVE_THREAD_NUMBER,

    VARRAY_SET,
    VARRAY_GET,

    // About Future
    FUTURE_INIT,

    FUTURE_IS_COMPLETE,  // cjnative only
    FUTURE_WAIT,  // cjnative only
    FUTURE_NOTIFYALL,  // cjnative only

    GET_THREAD_OBJECT,
    SET_THREAD_OBJECT,

    OVERFLOW_CHECKED_ADD,
    OVERFLOW_CHECKED_SUB,
    OVERFLOW_CHECKED_MUL,
    OVERFLOW_CHECKED_DIV,
    OVERFLOW_CHECKED_MOD,
    OVERFLOW_CHECKED_POW,
    OVERFLOW_CHECKED_INC,
    OVERFLOW_CHECKED_DEC,
    OVERFLOW_CHECKED_NEG,
    OVERFLOW_THROWING_ADD,
    OVERFLOW_THROWING_SUB,
    OVERFLOW_THROWING_MUL,
    OVERFLOW_THROWING_DIV,
    OVERFLOW_THROWING_MOD,
    OVERFLOW_THROWING_POW,
    OVERFLOW_THROWING_INC,
    OVERFLOW_THROWING_DEC,
    OVERFLOW_THROWING_NEG,
    OVERFLOW_SATURATING_ADD,
    OVERFLOW_SATURATING_SUB,
    OVERFLOW_SATURATING_MUL,
    OVERFLOW_SATURATING_DIV,
    OVERFLOW_SATURATING_MOD,
    OVERFLOW_SATURATING_POW,
    OVERFLOW_SATURATING_INC,
    OVERFLOW_SATURATING_DEC,
    OVERFLOW_SATURATING_NEG,
    OVERFLOW_WRAPPING_ADD,
    OVERFLOW_WRAPPING_SUB,
    OVERFLOW_WRAPPING_MUL,
    OVERFLOW_WRAPPING_DIV,
    OVERFLOW_WRAPPING_MOD,
    OVERFLOW_WRAPPING_POW,
    OVERFLOW_WRAPPING_INC,
    OVERFLOW_WRAPPING_DEC,
    OVERFLOW_WRAPPING_NEG,

    // llvm vector instructions for string optimization

    VECTOR_COMPARE_32,  // cjnative only
    VECTOR_INDEX_BYTE_32,  // cjnative only

    // Foreign functions translated to intrinsic functions in the interpreter,
    // These functions are not not marked as intrinsic in Cangjie but they are translated to intrinsics in BCHIR

    CJ_CORE_CAN_USE_SIMD,  // cjnative only

    CJ_TLS_DYN_SET_SESSION_CALLBACK,
    CJ_TLS_DYN_SSL_INIT,

    // ============================ cjnative only start =================
    REFLECTION_INTRINSIC_START_FLAG,

    IS_INTERFACE,
    IS_CLASS,
    IS_PRIMITIVE,
    IS_STRUCT,
    IS_GENERIC,
    GET_OR_CREATE_TYPEINFO_FOR_REFLECT,
    GET_TYPETEMPLATE,
    CHECK_METHOD_ACTUAL_ARGS,
    METHOD_ENTRYPOINT_IS_NULL,
    IS_RELECT_UNSUPPORTED_TYPE,
    GET_TYPE_FOR_ANY,
    GET_TYPE_BY_MANGLED_NAME,
    GET_TYPE_NAME,
    GET_TYPE_BY_QUALIFIED_NAME,
    GET_TYPE_QUALIFIED_NAME_LENGTH,
    GET_TYPE_QUALIFIED_NAME,
    GET_NUM_OF_INTERFACE,
    GET_INTERFACE,
    IS_SUBTYPE,
    GET_TYPE_INFO_MODIFIER,
    GET_TYPE_INFO_ANNOTATIONS,
    GET_OBJ_CLASS,
    GET_SUPER_TYPE_INFO,

    GET_NUM_OF_INSTANCE_METHOD_INFOS,
    GET_INSTANCE_METHOD_INFO,
    GET_NUM_OF_STATIC_METHOD_INFOS,
    GET_STATIC_METHOD_INFO,
    GET_METHOD_NAME,
    GET_METHOD_RETURN_TYPE,
    GET_METHOD_MODIFIER,
    GET_METHOD_ANNOTATIONS,
    APPLY_CJ_METHOD,
    APPLY_CJ_STATIC_METHOD,
    APPLY_CJ_GENERIC_METHOD,
    APPLY_CJ_GENERIC_STATIC_METHOD,
    GET_NUM_OF_ACTUAL_PARAMETERS,
    GET_NUM_OF_GENERIC_PARAMETERS,
    GET_ACTUAL_PARAMETER_INFO,
    GET_GENERIC_PARAMETER_INFO,

    GET_NUM_OF_INSTANCE_FIELD_INFOS,
    GET_INSTANCE_FIELD_INFO,
    GET_NUM_OF_STATIC_FIELD_INFOS,
    GET_STATIC_FIELD_INFO,
    GET_STATIC_FIELD_NAME,
    GET_STATIC_FIELD_TYPE,
    GET_STATIC_FIELD_ANNOTATIONS,
    GET_FIELD_NAME,
    GET_FIELD_TYPE,
    GET_FIELD_ANNOTATIONS,
    GET_FIELD_MODIFIER,
    GET_STATIC_FIELD_MODIFIER,
    GET_FIELD_VALUE,
    SET_FIELD_VALUE,
    GET_STATIC_FIELD_VALUE,
    SET_STATIC_FIELD_VALUE,
    GET_FIELD_DECLARING_TYPE,

    GET_PARAMETER_INDEX,
    GET_PARAMETER_NAME,
    GET_PARAMETER_TYPE,
    GET_PARAMETER_ANNOTATIONS,

    GET_RELATED_PACKAGE_INF,
    GET_PACKAGE_NAME,
    GET_PACKAGE_NUM_OF_TYPE_INFOS,
    GET_PACKAGE_TYPE_INFO,
    GET_PACKAGE_NUM_OF_GLOBAL_METHODS,
    GET_PACKAGE_GLOBAL_METHOD_INFO,
    GET_PACKAGE_NUM_OF_GLOBAL_FIELD_INFOS,
    GET_PACKAGE_GLOBAL_FIELD_INFO,
    LOAD_PACKAGE,
    GET_PACKAGE_BY_QUALIFIEDNAME,
    GET_PACKAGE_VERSION,
    GET_SUB_PACKAGES,

    REFLECTION_INTRINSIC_END_FLAG,
    // ============================ cjnative only end =================

    SLEEP,

    SOURCE_FILE,
    SOURCE_LINE,

    IDENTITY_HASHCODE,
    IDENTITY_HASHCODE_FOR_ARRAY,

    // ============================ cjnative only start =================
    // SYNC
    ATOMIC_LOAD,
    ATOMIC_STORE,
    ATOMIC_SWAP,
    ATOMIC_COMPARE_AND_SWAP,
    ATOMIC_FETCH_ADD,
    ATOMIC_FETCH_SUB,
    ATOMIC_FETCH_AND,
    ATOMIC_FETCH_OR,
    ATOMIC_FETCH_XOR,
    MUTEX_INIT,
    CJ_MUTEX_LOCK,
    MUTEX_TRY_LOCK,
    MUTEX_CHECK_STATUS,
    MUTEX_UNLOCK,
    WAITQUEUE_INIT,
    MONITOR_INIT,
    MOITIOR_WAIT,
    MOITIOR_NOTIFY,
    MOITIOR_NOTIFY_ALL,
    MULTICONDITION_WAIT,
    MULTICONDITION_NOTIFY,
    MULTICONDITION_NOTIFY_ALL,
    // ============================ cjnative only end =================

    // Syscall

    // AST lib FFI
    FFI_CJ_AST_LEX,
    FFI_CJ_AST_PARSEEXPR,
    FFI_CJ_AST_PARSEDECL,
    FFI_CJ_AST_PARSE_PROPMEMBERDECL,
    FFI_CJ_AST_PARSE_PRICONSTRUCTOR,
    FFI_CJ_AST_PARSE_PATTERN,
    FFI_CJ_AST_PARSE_TYPE,
    FFI_CJ_AST_PARSETOPLEVEL,
    FFI_CJ_AST_DIAGREPORT,

    // Macro With Context FFI
    FFI_CJ_PARENT_CONTEXT,
    FFI_CJ_MACRO_ITEM_INFO,
    FFI_CJ_GET_CHILD_MESSAGES,
    FFI_CJ_CHECK_ADD_SPACE,
    // CodeGen
    CG_UNSAFE_BEGIN,
    CG_UNSAFE_END,

    // C FFI funcs
    STRLEN,
    MEMCPY_S,
    MEMSET_S,
    FREE,
    MALLOC,
    STRCMP,
    MEMCMP,
    STRNCMP,
    STRCASECMP,

    // The interpreter is using these for cjnative backend as well
    ATOMIC_INT8_LOAD,
    ATOMIC_INT8_STORE,
    ATOMIC_INT8_SWAP,
    ATOMIC_INT8_CAS,
    ATOMIC_INT8_FETCH_ADD,
    ATOMIC_INT8_FETCH_SUB,
    ATOMIC_INT8_FETCH_AND,
    ATOMIC_INT8_FETCH_OR,
    ATOMIC_INT8_FETCH_XOR,

    ATOMIC_INT16_LOAD,
    ATOMIC_INT16_STORE,
    ATOMIC_INT16_SWAP,
    ATOMIC_INT16_CAS,
    ATOMIC_INT16_FETCH_ADD,
    ATOMIC_INT16_FETCH_SUB,
    ATOMIC_INT16_FETCH_AND,
    ATOMIC_INT16_FETCH_OR,
    ATOMIC_INT16_FETCH_XOR,

    ATOMIC_INT32_LOAD,
    ATOMIC_INT32_STORE,
    ATOMIC_INT32_SWAP,
    ATOMIC_INT32_CAS,
    ATOMIC_INT32_FETCH_ADD,
    ATOMIC_INT32_FETCH_SUB,
    ATOMIC_INT32_FETCH_AND,
    ATOMIC_INT32_FETCH_OR,
    ATOMIC_INT32_FETCH_XOR,

    ATOMIC_INT64_LOAD,
    ATOMIC_INT64_STORE,
    ATOMIC_INT64_SWAP,
    ATOMIC_INT64_CAS,
    ATOMIC_INT64_FETCH_ADD,
    ATOMIC_INT64_FETCH_SUB,
    ATOMIC_INT64_FETCH_AND,
    ATOMIC_INT64_FETCH_OR,
    ATOMIC_INT64_FETCH_XOR,

    ATOMIC_UINT8_LOAD,
    ATOMIC_UINT8_STORE,
    ATOMIC_UINT8_SWAP,
    ATOMIC_UINT8_CAS,
    ATOMIC_UINT8_FETCH_ADD,
    ATOMIC_UINT8_FETCH_SUB,
    ATOMIC_UINT8_FETCH_AND,
    ATOMIC_UINT8_FETCH_OR,
    ATOMIC_UINT8_FETCH_XOR,

    ATOMIC_UINT16_LOAD,
    ATOMIC_UINT16_STORE,
    ATOMIC_UINT16_SWAP,
    ATOMIC_UINT16_CAS,
    ATOMIC_UINT16_FETCH_ADD,
    ATOMIC_UINT16_FETCH_SUB,
    ATOMIC_UINT16_FETCH_AND,
    ATOMIC_UINT16_FETCH_OR,
    ATOMIC_UINT16_FETCH_XOR,

    ATOMIC_UINT32_LOAD,
    ATOMIC_UINT32_STORE,
    ATOMIC_UINT32_SWAP,
    ATOMIC_UINT32_CAS,
    ATOMIC_UINT32_FETCH_ADD,
    ATOMIC_UINT32_FETCH_SUB,
    ATOMIC_UINT32_FETCH_AND,
    ATOMIC_UINT32_FETCH_OR,
    ATOMIC_UINT32_FETCH_XOR,

    ATOMIC_UINT64_LOAD,
    ATOMIC_UINT64_STORE,
    ATOMIC_UINT64_SWAP,
    ATOMIC_UINT64_CAS,
    ATOMIC_UINT64_FETCH_ADD,
    ATOMIC_UINT64_FETCH_SUB,
    ATOMIC_UINT64_FETCH_AND,
    ATOMIC_UINT64_FETCH_OR,
    ATOMIC_UINT64_FETCH_XOR,

    ATOMIC_BOOL_LOAD,
    ATOMIC_BOOL_STORE,
    ATOMIC_BOOL_SWAP,
    ATOMIC_BOOL_CAS,

    ATOMIC_REFERENCEBASE_LOAD,
    ATOMIC_REFERENCEBASE_STORE,
    ATOMIC_REFERENCEBASE_SWAP,
    ATOMIC_REFERENCEBASE_CAS,

    ATOMIC_OPTIONREFERENCE_LOAD,
    ATOMIC_OPTIONREFERENCE_STORE,
    ATOMIC_OPTIONREFERENCE_SWAP,
    ATOMIC_OPTIONREFERENCE_CAS,

    // CHIR 2: Exception intrinsic
    BEGIN_CATCH,

    // CHIR 2: Math intrinsic
    ABS,
    FABS,
    FLOOR,
    CEIL,
    TRUNC,
    SIN,
    COS,
    EXP,
    EXP2,
    LOG,
    LOG2,
    LOG10,
    SQRT,
    ROUND,
    POW,
    POWI,
    BIT_CAST,
}

table Expression {
base: Base;
kind: CHIRExprKind;
expressionID: uint32;
operands: [uint32]; // use valueID
blockGroups: [uint32]; // use valueID
parentBlock: uint32; // use valueID
resultLocalVar: uint32; // use valueID
resultTy: uint32; // use typeID
}

table UnaryExpression {
base: Expression;
overflowStrategy: OverflowStrategy;
}

table BinaryExpression {
base: Expression;
overflowStrategy: OverflowStrategy;
}

table Constant {
base: Expression;
genericArgs: [uint32]; // use typeID
}

table Allocate {
base: Expression;
targetType: uint32; // use typeID
}

table Load {
base: Expression;
}

table Store {
base: Expression;
}

table GetElementRef {
base: Expression;
path: [uint64];
}

table StoreElementRef {
base: Expression;
path: [uint64];
}

table Apply {
base: Expression;
genericArgs: [uint32]; // use typeID
isSuperCall: bool;
}

table Invoke {
base: Expression;
methodName: string;
methodType: uint32; // use typeID
}

table TypeCast {
base: Expression;
targetType: uint32; // use typeID
overflowStrategy: OverflowStrategy;
}

table InstanceOf {
base: Expression;
targetType: uint32; // use typeID
}

table Box {
base: Expression;
targetType: uint64; // use typeID
}

table UnBox {
base: Expression;
targetType: uint64; // use typeID
}

table Terminator {
base: Expression;
successors: [uint32]; // use valueID
}

table GoTo {
base: Terminator;
}

table Branch {
base: Terminator;
sourceExpr: SourceExpr;
}

table MultiBranch {
base: Terminator;
caseVals: [uint64];
}

table Exit {
base: Terminator;
}

table RaiseException {
base: Terminator;
}

table ApplyWithException {
base: Terminator;
genericArgs: [uint32]; // use typeID
}

table InvokeWithException {
base: Terminator;
methodName: string;
methodType: uint32; // use typeID
}

table IntOpWithException {
base: Terminator;
opKind: CHIRExprKind;
}

table TypeCastWithException {
base: Terminator;
targetType: uint32; // use typeID
}

table IntrinsicWithException {
base: Terminator;
intrinsicKind: IntrinsicKind;
genericArgs: [uint32]; // use typeID
}

table AllocateWithException {
base: Terminator;
targetType: uint32; // use typeID
}

table RawArrayAllocateWithException {
base: Terminator;
elementType: uint32; // use typeID
}

table RawArrayLiteralAllocateWithException {
base: Terminator;
elementType: uint32; // use typeID
}

table SpawnWithException {
base: Terminator;
isExecuteClosure: bool;
executeClosure: uint32;  // use valueID
}

table Tuple {
base: Expression;
}

table Field {
base: Expression;
path: [uint64];
}

table RawArrayAllocate {
base: Expression;
elementType: uint32; // use typeID
}

table RawArrayLiteralAllocate {
base: Expression;
elementType: uint32; // use typeID
}

table RawArrayLiteralInit {
base: Expression;
}

table RawArrayInitByValue {
base: Expression;
}

table VArray {
base: Expression;
}

table VArrayBd {
base: Expression;
}

table GetException {
base: Expression;
}

table Intrinsic {
base: Expression;
intrinsicKind: IntrinsicKind;
genericArgs: [uint32]; // use typeID
}

table If {
base: Expression;
}

table Loop {
base: Expression;
}

table ForInRange {
base: Expression;
}

table ForInIter {
base: Expression;
}

table ForInClosedRange {
base: Expression;
}

table Debug {
base: Expression;
srcCodeIdentifier: string;
accurateEnvObjTy: uint32; // use typeID
}

table Spawn {
base: Expression;
isExecuteClosure: bool;
executeClosure: uint32;  // use valueID
}

table Lambda {
base: Expression;
funcTy: uint32; // use typeID
isLocalFunc: bool;
identifier: string;
srcCodeIdentifier: string;
params: [uint32];  // use valueID
genericTypeParams: [uint32]; // use typeID
capturedVars: [uint32];  // use valueID
}

table InvokeStatic {
base: Expression;
methodName: string;
methodType: uint32; // use typeID
classType: uint32; // use typeID
}

table InvokeStaticWithException {
base: Terminator;
methodName: string;
methodType: uint32; // use typeID
classType: uint32; // use typeID
}

union TypeElem {
	RuneType,
	BooleanType,
	UnitType,
	NothingType,
	IntType,
	FloatType,
	TupleType,
	ClosureType,
	RawArrayType,
	VArrayType,
	FuncType,
	EnumType,
	StructType,
	ClassType,
	CStringType,
	CPointerType,
	GenericType,
	RefType,
    BoxType,
	VoidType,
}

union CustomTypeDefElem {
	EnumDef,
	StructDef,
	ClassDef,
}

union ExpressionElem {
	UnaryExpression,
	BinaryExpression,
	Constant,
	Allocate,
	Load,
	Store,
	GetElementRef,
	StoreElementRef,
	Apply,
	Invoke,
	TypeCast,
	InstanceOf,
	Box,
	UnBox,
	GoTo,
	Branch,
	MultiBranch,
	Exit,
	RaiseException,
	ApplyWithException,
	InvokeWithException,
	IntOpWithException,
	TypeCastWithException,
	IntrinsicWithException,
	AllocateWithException,
	RawArrayAllocateWithException,
	SpawnWithException,
	Tuple,
	Field,
	RawArrayAllocate,
	RawArrayLiteralInit,
	RawArrayInitByValue,
	VArray,
	VArrayBd,
	GetException,
	Intrinsic,
	If,
	Loop,
	ForInRange,
    ForInIter,
    ForInClosedRange,
	Debug,
	Spawn,
	Lambda,
	InvokeStatic,
	InvokeStaticWithException,
}

union ValueElem {
	BoolLiteral,
	RuneLiteral,
	StringLiteral,
	IntLiteral,
	FloatLiteral,
	UnitLiteral,
	NullLiteral,
	Parameter,
	LocalVar,
	GlobalVar,
	Func,
	ImportedVar,
	ImportedFunc,
	Block,
	BlockGroup,
}

table CHIRPackage {
name: string;
path: string;
pkgAccessLevel: string;
types: [TypeElem];
values: [ValueElem];
exprs: [ExpressionElem];
defs: [CustomTypeDefElem];
globalInitFunc: uint32;  // use valueID (Func)
}

root_type CHIRPackage;