LLVM initialization
This commit is contained in:
parent
7ad2bca45c
commit
9b1c5ce7b0
215
src/compiler.bbb
215
src/compiler.bbb
@ -531,6 +531,32 @@ fail = fn () noreturn
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMContext = opaque;
|
||||||
|
LLVMModule = opaque;
|
||||||
|
|
||||||
|
LLVMBuilder = opaque;
|
||||||
|
|
||||||
|
LLVMValue = opaque;
|
||||||
|
LLVMType = opaque;
|
||||||
|
LLVMBasicBlock = opaque;
|
||||||
|
LLVMIntrinsicId = typealias u32;
|
||||||
|
|
||||||
|
LLVMMetadata = opaque;
|
||||||
|
LLVMDIBuilder = opaque;
|
||||||
|
|
||||||
|
LLVMTarget = opaque;
|
||||||
|
LLVMTargetDataLayout = opaque;
|
||||||
|
LLVMTargetMachine = opaque;
|
||||||
|
LLVMTargetMachineOptions = opaque;
|
||||||
|
|
||||||
|
LLVMIntrinsicIndex = enum u32
|
||||||
|
{
|
||||||
|
trap,
|
||||||
|
va_start,
|
||||||
|
va_end,
|
||||||
|
va_copy,
|
||||||
|
}
|
||||||
|
|
||||||
CompilerCommand = enum
|
CompilerCommand = enum
|
||||||
{
|
{
|
||||||
compile,
|
compile,
|
||||||
@ -548,6 +574,15 @@ BuildMode = enum
|
|||||||
aggressively_optimize_for_size,
|
aggressively_optimize_for_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_mode_is_optimized = fn (build_mode: BuildMode) u1
|
||||||
|
{
|
||||||
|
switch (build_mode)
|
||||||
|
{
|
||||||
|
.debug_none, .debug => { return 0; },
|
||||||
|
else => { return 1; },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CompileFile = struct
|
CompileFile = struct
|
||||||
{
|
{
|
||||||
relative_file_path: []u8,
|
relative_file_path: []u8,
|
||||||
@ -644,6 +679,7 @@ Scope = struct
|
|||||||
{
|
{
|
||||||
types: TypeList,
|
types: TypeList,
|
||||||
parent: &Scope,
|
parent: &Scope,
|
||||||
|
llvm: &LLVMMetadata,
|
||||||
line: u32,
|
line: u32,
|
||||||
column: u32,
|
column: u32,
|
||||||
kind: ScopeKind,
|
kind: ScopeKind,
|
||||||
@ -821,31 +857,6 @@ MacroInstantiation = struct
|
|||||||
foo: u32,
|
foo: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMContext = opaque;
|
|
||||||
LLVMModule = opaque;
|
|
||||||
|
|
||||||
LLVMBuilder = opaque;
|
|
||||||
|
|
||||||
LLVMValue = opaque;
|
|
||||||
LLVMType = opaque;
|
|
||||||
LLVMBasicBlock = opaque;
|
|
||||||
LLVMIntrinsicId = typealias u32;
|
|
||||||
|
|
||||||
LLVMMetadata = opaque;
|
|
||||||
LLVMDIBuilder = opaque;
|
|
||||||
|
|
||||||
LLVMTarget = opaque;
|
|
||||||
LLVMTargetMachine = opaque;
|
|
||||||
LLVMTargetMachineOptions = opaque;
|
|
||||||
|
|
||||||
LLVMIntrinsicIndex = enum
|
|
||||||
{
|
|
||||||
trap,
|
|
||||||
va_start,
|
|
||||||
va_end,
|
|
||||||
va_copy,
|
|
||||||
}
|
|
||||||
|
|
||||||
[extern] LLVMInitializeX86TargetInfo = fn [cc(c)] () void;
|
[extern] LLVMInitializeX86TargetInfo = fn [cc(c)] () void;
|
||||||
[extern] LLVMInitializeX86Target = fn [cc(c)] () void;
|
[extern] LLVMInitializeX86Target = fn [cc(c)] () void;
|
||||||
[extern] LLVMInitializeX86TargetMC = fn [cc(c)] () void;
|
[extern] LLVMInitializeX86TargetMC = fn [cc(c)] () void;
|
||||||
@ -882,7 +893,7 @@ llvm_initialize_targets = fn () void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMCodeGenerationOptimizationLevel = enum
|
LLVMCodeGenerationOptimizationLevel = enum u32
|
||||||
{
|
{
|
||||||
none = 0,
|
none = 0,
|
||||||
less = 1,
|
less = 1,
|
||||||
@ -890,16 +901,109 @@ LLVMCodeGenerationOptimizationLevel = enum
|
|||||||
aggressive = 3,
|
aggressive = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMDwarfSourceLanguage = enum u32
|
||||||
|
{
|
||||||
|
C89,
|
||||||
|
C,
|
||||||
|
Ada83,
|
||||||
|
C_plus_plus,
|
||||||
|
Cobol74,
|
||||||
|
Cobol85,
|
||||||
|
Fortran77,
|
||||||
|
Fortran90,
|
||||||
|
Pascal83,
|
||||||
|
Modula2,
|
||||||
|
// New in DWARF v3:
|
||||||
|
Java,
|
||||||
|
C99,
|
||||||
|
Ada95,
|
||||||
|
Fortran95,
|
||||||
|
PLI,
|
||||||
|
ObjC,
|
||||||
|
ObjC_plus_plus,
|
||||||
|
UPC,
|
||||||
|
D,
|
||||||
|
// New in DWARF v4:
|
||||||
|
Python,
|
||||||
|
// New in DWARF v5:
|
||||||
|
OpenCL,
|
||||||
|
Go,
|
||||||
|
Modula3,
|
||||||
|
Haskell,
|
||||||
|
C_plus_plus_03,
|
||||||
|
C_plus_plus_11,
|
||||||
|
OCaml,
|
||||||
|
Rust,
|
||||||
|
C11,
|
||||||
|
Swift,
|
||||||
|
Julia,
|
||||||
|
Dylan,
|
||||||
|
C_plus_plus_14,
|
||||||
|
Fortran03,
|
||||||
|
Fortran08,
|
||||||
|
RenderScript,
|
||||||
|
BLISS,
|
||||||
|
Kotlin,
|
||||||
|
Zig,
|
||||||
|
Crystal,
|
||||||
|
C_plus_plus_17,
|
||||||
|
C_plus_plus_20,
|
||||||
|
C17,
|
||||||
|
Fortran18,
|
||||||
|
Ada2005,
|
||||||
|
Ada2012,
|
||||||
|
HIP,
|
||||||
|
Assembly,
|
||||||
|
C_sharp,
|
||||||
|
Mojo,
|
||||||
|
GLSL,
|
||||||
|
GLSL_ES,
|
||||||
|
HLSL,
|
||||||
|
OpenCL_CPP,
|
||||||
|
CPP_for_OpenCL,
|
||||||
|
SYCL,
|
||||||
|
Ruby,
|
||||||
|
Move,
|
||||||
|
Hylo,
|
||||||
|
Metal,
|
||||||
|
|
||||||
|
// Vendor extensions:
|
||||||
|
Mips_Assembler,
|
||||||
|
GOOGLE_RenderScript,
|
||||||
|
BORLAND_Delphi
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMDwarfEmissionKind = enum u32
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
full,
|
||||||
|
line_tables_only,
|
||||||
|
}
|
||||||
|
|
||||||
[extern] LLVMContextCreate = fn [cc(c)] () &LLVMContext;
|
[extern] LLVMContextCreate = fn [cc(c)] () &LLVMContext;
|
||||||
[extern] llvm_context_create_module = fn (context: &LLVMContext, name: []u8) &LLVMModule;
|
[extern] llvm_context_create_module = fn (context: &LLVMContext, name: []u8) &LLVMModule;
|
||||||
[extern] LLVMCreateBuilderInContext = fn (context: &LLVMContext) &LLVMBuilder;
|
[extern] LLVMCreateBuilderInContext = fn (context: &LLVMContext) &LLVMBuilder;
|
||||||
|
|
||||||
|
[extern] LLVMVoidTypeInContext = fn [cc(c)] (context: &LLVMContext) &LLVMType;
|
||||||
|
[extern] LLVMPointerTypeInContext = fn [cc(c)] (context: &LLVMContext, address_space: u32) &LLVMType;
|
||||||
|
|
||||||
|
[extern] LLVMCreateDIBuilder = fn (module: &LLVMModule) &LLVMDIBuilder;
|
||||||
|
[extern] LLVMDIBuilderCreateFile = fn (di_builder: &LLVMDIBuilder, file_pointer: &u8, file_length: u64, directory_pointer: &u8, directory_length: u64) &LLVMMetadata;
|
||||||
|
[extern] LLVMDIBuilderCreateCompileUnit = fn (di_builder: &LLVMDIBuilder, language: LLVMDwarfSourceLanguage, file: &LLVMMetadata, producer_name_pointer: &u8, producer_name_length: u64, is_optimized: s32, flags_pointer: &u8, flags_length: u64, runtime_version: u32, split_name_pointer: &u8, split_name_length: u64, emission_kind: LLVMDwarfEmissionKind, dwo_id: u32, split_debug_inlining: s32, debug_info_for_profiling: s32, sysroot_pointer: &u8, sysroot_length: u64, sdk_pointer: &u8, sdk_length: u64) &LLVMMetadata;
|
||||||
|
|
||||||
|
[extern] LLVMLookupIntrinsicID = fn [cc(c)] (name_pointer: &u8, name_length: u64) LLVMIntrinsicId;
|
||||||
|
|
||||||
[extern] LLVMCreateTargetMachineOptions = fn () &LLVMTargetMachineOptions;
|
[extern] LLVMCreateTargetMachineOptions = fn () &LLVMTargetMachineOptions;
|
||||||
[extern] LLVMTargetMachineOptionsSetCPU = fn (target_machine_options: &LLVMTargetMachineOptions, cpu: &u8) void;
|
[extern] LLVMTargetMachineOptionsSetCPU = fn (target_machine_options: &LLVMTargetMachineOptions, cpu: &u8) void;
|
||||||
[extern] LLVMTargetMachineOptionsSetFeatures = fn (target_machine_options: &LLVMTargetMachineOptions, features: &u8) void;
|
[extern] LLVMTargetMachineOptionsSetFeatures = fn (target_machine_options: &LLVMTargetMachineOptions, features: &u8) void;
|
||||||
[extern] LLVMTargetMachineOptionsSetCodeGenOptLevel = fn (target_machine_options: &LLVMTargetMachineOptions, optimization_level: LLVMCodeGenerationOptimizationLevel) void;
|
[extern] LLVMTargetMachineOptionsSetCodeGenOptLevel = fn (target_machine_options: &LLVMTargetMachineOptions, optimization_level: LLVMCodeGenerationOptimizationLevel) void;
|
||||||
[extern] LLVMGetTargetFromTriple = fn (target_triple: &u8, target_pointer: &&LLVMTarget, error_message_pointer: &&u8) s32;
|
[extern] LLVMGetTargetFromTriple = fn (target_triple: &u8, target_pointer: &&LLVMTarget, error_message_pointer: &&u8) s32;
|
||||||
[extern] LLVMCreateTargetMachineWithOptions = fn (target: &LLVMTarget, target_triple: &u8, target_machine_options: &LLVMTargetMachineOptions) &LLVMTargetMachine;
|
[extern] LLVMCreateTargetMachineWithOptions = fn (target: &LLVMTarget, target_triple: &u8, target_machine_options: &LLVMTargetMachineOptions) &LLVMTargetMachine;
|
||||||
|
[extern] LLVMCreateTargetDataLayout = fn (target_machine: &LLVMTargetMachine) &LLVMTargetDataLayout;
|
||||||
|
[extern] LLVMSetModuleDataLayout = fn (module: &LLVMModule, target_data_layout: &LLVMTargetDataLayout) void;
|
||||||
|
[extern] LLVMSetTarget = fn (module: &LLVMModule, target_triple: &u8) void;
|
||||||
|
|
||||||
|
default_address_space: u32 = 0;
|
||||||
|
|
||||||
ModuleLLVM = struct
|
ModuleLLVM = struct
|
||||||
{
|
{
|
||||||
@ -908,7 +1012,8 @@ ModuleLLVM = struct
|
|||||||
builder: &LLVMBuilder,
|
builder: &LLVMBuilder,
|
||||||
di_builder: &LLVMDIBuilder,
|
di_builder: &LLVMDIBuilder,
|
||||||
file: &LLVMMetadata,
|
file: &LLVMMetadata,
|
||||||
compile_unit: &LLVMMetadata,
|
target_machine: &LLVMTargetMachine,
|
||||||
|
target_data_layout: &LLVMTargetDataLayout,
|
||||||
pointer_type: &LLVMType,
|
pointer_type: &LLVMType,
|
||||||
void_type: &LLVMType,
|
void_type: &LLVMType,
|
||||||
intrinsic_table: enum_array[LLVMIntrinsicIndex](LLVMIntrinsicId),
|
intrinsic_table: enum_array[LLVMIntrinsicIndex](LLVMIntrinsicId),
|
||||||
@ -2689,6 +2794,36 @@ emit = fn (module: &Module) void
|
|||||||
>m = llvm_context_create_module(context, module.name);
|
>m = llvm_context_create_module(context, module.name);
|
||||||
>builder = LLVMCreateBuilderInContext(context);
|
>builder = LLVMCreateBuilderInContext(context);
|
||||||
|
|
||||||
|
>di_builder: &LLVMDIBuilder = zero;
|
||||||
|
>di_file: &LLVMMetadata = zero;
|
||||||
|
|
||||||
|
if (module.has_debug_info)
|
||||||
|
{
|
||||||
|
di_builder = LLVMCreateDIBuilder(m);
|
||||||
|
>last_slash = string_last_character(module.path, '/');
|
||||||
|
if (last_slash == string_no_match)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
>directory = module.path[..last_slash];
|
||||||
|
>file_name = module.path[last_slash + 1..];
|
||||||
|
|
||||||
|
>di_file = LLVMDIBuilderCreateFile(di_builder, file_name.pointer, file_name.length, directory.pointer, directory.length);
|
||||||
|
|
||||||
|
>language: LLVMDwarfSourceLanguage = .C17;
|
||||||
|
>producer_name = "bloat buster";
|
||||||
|
>is_optimized = build_mode_is_optimized(module.build_mode);
|
||||||
|
>flags = "";
|
||||||
|
>emission_kind: LLVMDwarfEmissionKind = .full;
|
||||||
|
>runtime_version: u32 = 0;
|
||||||
|
>split_name = "";
|
||||||
|
>sysroot = "";
|
||||||
|
>sdk = "";
|
||||||
|
|
||||||
|
module.scope.llvm = LLVMDIBuilderCreateCompileUnit(di_builder, language, di_file, producer_name.pointer, producer_name.length, #extend(is_optimized), flags.pointer, flags.length, runtime_version, split_name.pointer, split_name.length, emission_kind, 0, 0, #extend(is_optimized), sysroot.pointer, sysroot.length, sdk.pointer, sdk.length);
|
||||||
|
}
|
||||||
|
|
||||||
>target_triple: []u8 = undefined;
|
>target_triple: []u8 = undefined;
|
||||||
>cpu_model: []u8 = undefined;
|
>cpu_model: []u8 = undefined;
|
||||||
>cpu_features: []u8 = undefined;
|
>cpu_features: []u8 = undefined;
|
||||||
@ -2729,7 +2864,31 @@ emit = fn (module: &Module) void
|
|||||||
|
|
||||||
assert(!error_message);
|
assert(!error_message);
|
||||||
|
|
||||||
LLVMCreateTargetMachineWithOptions(target, target_triple.pointer, target_machine_options);
|
>target_machine = LLVMCreateTargetMachineWithOptions(target, target_triple.pointer, target_machine_options);
|
||||||
|
|
||||||
|
>target_data_layout = LLVMCreateTargetDataLayout(target_machine);
|
||||||
|
LLVMSetModuleDataLayout(m, target_data_layout);
|
||||||
|
LLVMSetTarget(m, target_triple.pointer);
|
||||||
|
|
||||||
|
module.llvm = {
|
||||||
|
.context = context,
|
||||||
|
.module = m,
|
||||||
|
.builder = builder,
|
||||||
|
.di_builder = di_builder,
|
||||||
|
.file = di_file,
|
||||||
|
.target_machine = target_machine,
|
||||||
|
.target_data_layout = target_data_layout,
|
||||||
|
.pointer_type = LLVMPointerTypeInContext(context, default_address_space),
|
||||||
|
.void_type = LLVMVoidTypeInContext(context),
|
||||||
|
zero,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i: 0..module.llvm.intrinsic_table.length)
|
||||||
|
{
|
||||||
|
>e: LLVMIntrinsicIndex = #enum_from_int(i);
|
||||||
|
>name = #enum_name(e);
|
||||||
|
module.llvm.intrinsic_table[i] = LLVMLookupIntrinsicID(name.pointer, name.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compile = fn (arena: &Arena, options: CompileOptions) void
|
compile = fn (arena: &Arena, options: CompileOptions) void
|
||||||
|
@ -597,6 +597,7 @@ fn u32 get_byte_alignment(Type* type)
|
|||||||
return result;
|
return result;
|
||||||
} break;
|
} break;
|
||||||
case TypeId::pointer:
|
case TypeId::pointer:
|
||||||
|
case TypeId::opaque:
|
||||||
{
|
{
|
||||||
return 8;
|
return 8;
|
||||||
} break;
|
} break;
|
||||||
@ -860,6 +861,7 @@ enum class UnaryId
|
|||||||
bitwise_not,
|
bitwise_not,
|
||||||
dereference,
|
dereference,
|
||||||
pointer_from_int,
|
pointer_from_int,
|
||||||
|
enum_from_int,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ValueUnary
|
struct ValueUnary
|
||||||
|
188
src/emitter.cpp
188
src/emitter.cpp
@ -176,6 +176,7 @@ fn bool is_promotable_integer_type_for_abi(Type* type)
|
|||||||
case TypeId::bits: return is_promotable_integer_type_for_abi(type->bits.backing_type);
|
case TypeId::bits: return is_promotable_integer_type_for_abi(type->bits.backing_type);
|
||||||
case TypeId::alias: return is_promotable_integer_type_for_abi(type->alias.type);
|
case TypeId::alias: return is_promotable_integer_type_for_abi(type->alias.type);
|
||||||
case TypeId::enumerator: return is_promotable_integer_type_for_abi(type->enumerator.backing_type);
|
case TypeId::enumerator: return is_promotable_integer_type_for_abi(type->enumerator.backing_type);
|
||||||
|
case TypeId::pointer: return false;
|
||||||
default: unreachable();
|
default: unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -927,6 +928,7 @@ fn void resolve_type_in_place_abi(Module* module, Type* type)
|
|||||||
result = LLVMIntTypeInContext(module->llvm.context, type->integer.bit_count);
|
result = LLVMIntTypeInContext(module->llvm.context, type->integer.bit_count);
|
||||||
break;
|
break;
|
||||||
case TypeId::pointer:
|
case TypeId::pointer:
|
||||||
|
case TypeId::opaque:
|
||||||
result = module->llvm.pointer_type;
|
result = module->llvm.pointer_type;
|
||||||
break;
|
break;
|
||||||
case TypeId::array:
|
case TypeId::array:
|
||||||
@ -1015,6 +1017,7 @@ fn void resolve_type_in_place_memory(Module* module, Type* type)
|
|||||||
case TypeId::void_type:
|
case TypeId::void_type:
|
||||||
case TypeId::noreturn:
|
case TypeId::noreturn:
|
||||||
case TypeId::pointer:
|
case TypeId::pointer:
|
||||||
|
case TypeId::opaque:
|
||||||
case TypeId::array:
|
case TypeId::array:
|
||||||
case TypeId::structure:
|
case TypeId::structure:
|
||||||
case TypeId::enum_array:
|
case TypeId::enum_array:
|
||||||
@ -2220,6 +2223,7 @@ fn bool unary_is_boolean(UnaryId id)
|
|||||||
case UnaryId::bitwise_not:
|
case UnaryId::bitwise_not:
|
||||||
case UnaryId::dereference:
|
case UnaryId::dereference:
|
||||||
case UnaryId::pointer_from_int:
|
case UnaryId::pointer_from_int:
|
||||||
|
case UnaryId::enum_from_int:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2265,7 +2269,20 @@ fn bool binary_is_shortcircuiting(BinaryId id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void analyze_type(Module* module, Value* value, Type* expected_type, bool must_be_constant);
|
enum class IndexType
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
array,
|
||||||
|
enum_array,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TypeAnalysis
|
||||||
|
{
|
||||||
|
bool must_be_constant;
|
||||||
|
bool is_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnalysis analysis);
|
||||||
|
|
||||||
fn void analyze_binary_type(Module* module, Value* left, Value* right, bool is_boolean, Type* expected_type, bool must_be_constant)
|
fn void analyze_binary_type(Module* module, Value* left, Value* right, bool is_boolean, Type* expected_type, bool must_be_constant)
|
||||||
{
|
{
|
||||||
@ -2296,19 +2313,19 @@ fn void analyze_binary_type(Module* module, Value* left, Value* right, bool is_b
|
|||||||
{
|
{
|
||||||
if (left_constant)
|
if (left_constant)
|
||||||
{
|
{
|
||||||
analyze_type(module, right, 0, must_be_constant);
|
analyze_type(module, right, 0, { .must_be_constant = must_be_constant });
|
||||||
analyze_type(module, left, right->type, must_be_constant);
|
analyze_type(module, left, right->type, { .must_be_constant = must_be_constant });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
analyze_type(module, left, 0, must_be_constant);
|
analyze_type(module, left, 0, { .must_be_constant = must_be_constant });
|
||||||
analyze_type(module, right, left->type, must_be_constant);
|
analyze_type(module, right, left->type, { .must_be_constant = must_be_constant });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!is_boolean && expected_type)
|
else if (!is_boolean && expected_type)
|
||||||
{
|
{
|
||||||
analyze_type(module, left, expected_type, must_be_constant);
|
analyze_type(module, left, expected_type, { .must_be_constant = must_be_constant });
|
||||||
analyze_type(module, right, expected_type, must_be_constant);
|
analyze_type(module, right, expected_type, { .must_be_constant = must_be_constant });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2622,9 +2639,8 @@ fn void copy_block(Module* module, Scope* parent_scope, BlockCopy copy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void analyze_type(Module* module, Value* value, Type* expected_type, bool must_be_constant)
|
fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnalysis analysis)
|
||||||
{
|
{
|
||||||
unused(must_be_constant);
|
|
||||||
assert(!value->type);
|
assert(!value->type);
|
||||||
assert(!value->llvm);
|
assert(!value->llvm);
|
||||||
|
|
||||||
@ -2674,6 +2690,14 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
case ValueId::constant_integer:
|
case ValueId::constant_integer:
|
||||||
{
|
{
|
||||||
|
if (!expected_type)
|
||||||
|
{
|
||||||
|
if (analysis.is_index)
|
||||||
|
{
|
||||||
|
expected_type = uint64(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!expected_type)
|
if (!expected_type)
|
||||||
{
|
{
|
||||||
report_error();
|
report_error();
|
||||||
@ -2726,7 +2750,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto extended_value = unary_value;
|
auto extended_value = unary_value;
|
||||||
analyze_type(module, extended_value, 0, must_be_constant);
|
analyze_type(module, extended_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto source = extended_value->type;
|
auto source = extended_value->type;
|
||||||
assert(source);
|
assert(source);
|
||||||
|
|
||||||
@ -2750,7 +2774,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto expected_bit_size = get_bit_size(expected_type);
|
auto expected_bit_size = get_bit_size(expected_type);
|
||||||
auto source_bit_size = get_bit_size(unary_value->type);
|
auto source_bit_size = get_bit_size(unary_value->type);
|
||||||
|
|
||||||
@ -2763,7 +2787,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
} break;
|
} break;
|
||||||
case UnaryId::dereference:
|
case UnaryId::dereference:
|
||||||
{
|
{
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
if (value->kind == ValueKind::left)
|
if (value->kind == ValueKind::left)
|
||||||
{
|
{
|
||||||
report_error();
|
report_error();
|
||||||
@ -2777,7 +2801,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
} break;
|
} break;
|
||||||
case UnaryId::int_from_enum:
|
case UnaryId::int_from_enum:
|
||||||
{
|
{
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
auto value_enum_type = unary_value->type;
|
auto value_enum_type = unary_value->type;
|
||||||
if (value_enum_type->id != TypeId::enumerator)
|
if (value_enum_type->id != TypeId::enumerator)
|
||||||
@ -2792,7 +2816,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
} break;
|
} break;
|
||||||
case UnaryId::int_from_pointer:
|
case UnaryId::int_from_pointer:
|
||||||
{
|
{
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
auto value_enum_type = unary_value->type;
|
auto value_enum_type = unary_value->type;
|
||||||
if (value_enum_type->id != TypeId::pointer)
|
if (value_enum_type->id != TypeId::pointer)
|
||||||
@ -2815,7 +2839,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto value_pointer_type = unary_value->type;
|
auto value_pointer_type = unary_value->type;
|
||||||
if (value_pointer_type == expected_type)
|
if (value_pointer_type == expected_type)
|
||||||
{
|
{
|
||||||
@ -2833,7 +2857,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
auto string_type = get_slice_type(module, uint8(module));
|
auto string_type = get_slice_type(module, uint8(module));
|
||||||
typecheck(module, expected_type, string_type);
|
typecheck(module, expected_type, string_type);
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto enum_type = unary_value->type;
|
auto enum_type = unary_value->type;
|
||||||
if (enum_type->id != TypeId::enumerator)
|
if (enum_type->id != TypeId::enumerator)
|
||||||
{
|
{
|
||||||
@ -2948,7 +2972,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto unary_value_type = unary_value->type;
|
auto unary_value_type = unary_value->type;
|
||||||
if (unary_value_type->id != TypeId::integer)
|
if (unary_value_type->id != TypeId::integer)
|
||||||
{
|
{
|
||||||
@ -2961,6 +2985,32 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_type = expected_type;
|
||||||
|
} break;
|
||||||
|
case UnaryId::enum_from_int:
|
||||||
|
{
|
||||||
|
if (!expected_type)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_type->id != TypeId::enumerator)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
analyze_type(module, unary_value, expected_type->enumerator.backing_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
auto unary_value_type = unary_value->type;
|
||||||
|
if (unary_value_type->id != TypeId::integer)
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_bit_size(unary_value_type) != get_bit_size(expected_type))
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
value_type = expected_type;
|
value_type = expected_type;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
@ -2968,12 +3018,12 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
auto is_boolean = unary_is_boolean(unary_id);
|
auto is_boolean = unary_is_boolean(unary_id);
|
||||||
if (is_boolean)
|
if (is_boolean)
|
||||||
{
|
{
|
||||||
analyze_type(module, unary_value, 0, must_be_constant);
|
analyze_type(module, unary_value, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
value_type = uint1(module);
|
value_type = uint1(module);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
analyze_type(module, unary_value, expected_type, must_be_constant);
|
analyze_type(module, unary_value, expected_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
value_type = unary_value->type;
|
value_type = unary_value->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3031,7 +3081,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
case ValueId::binary:
|
case ValueId::binary:
|
||||||
{
|
{
|
||||||
auto is_boolean = binary_is_boolean(value->binary.id);
|
auto is_boolean = binary_is_boolean(value->binary.id);
|
||||||
analyze_binary_type(module, value->binary.left, value->binary.right, is_boolean, expected_type, must_be_constant);
|
analyze_binary_type(module, value->binary.left, value->binary.right, is_boolean, expected_type, analysis.must_be_constant);
|
||||||
check_types(module, value->binary.left->type, value->binary.right->type);
|
check_types(module, value->binary.left->type, value->binary.right->type);
|
||||||
|
|
||||||
value_type = is_boolean ? uint1(module) : value->binary.left->type;
|
value_type = is_boolean ? uint1(module) : value->binary.left->type;
|
||||||
@ -3050,7 +3100,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
auto call = &value->call;
|
auto call = &value->call;
|
||||||
auto callable = call->callable;
|
auto callable = call->callable;
|
||||||
analyze_type(module, callable, 0, must_be_constant);
|
analyze_type(module, callable, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
Type* function_type = 0;
|
Type* function_type = 0;
|
||||||
switch (callable->id)
|
switch (callable->id)
|
||||||
{
|
{
|
||||||
@ -3101,14 +3151,14 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
auto* argument_type = semantic_argument_types[i];
|
auto* argument_type = semantic_argument_types[i];
|
||||||
auto* call_argument = call_arguments[i];
|
auto* call_argument = call_arguments[i];
|
||||||
analyze_type(module, call_argument, argument_type, must_be_constant);
|
analyze_type(module, call_argument, argument_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
check_types(module, argument_type, call_argument->type);
|
check_types(module, argument_type, call_argument->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = semantic_argument_types.length; i < call_arguments.length; i += 1)
|
for (u64 i = semantic_argument_types.length; i < call_arguments.length; i += 1)
|
||||||
{
|
{
|
||||||
auto* call_argument = call_arguments[i];
|
auto* call_argument = call_arguments[i];
|
||||||
analyze_type(module, call_argument, 0, must_be_constant);
|
analyze_type(module, call_argument, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto semantic_return_type = function_type->function.semantic_return_type;
|
auto semantic_return_type = function_type->function.semantic_return_type;
|
||||||
@ -3144,7 +3194,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
auto* element_type = expected_type->array.element_type;
|
auto* element_type = expected_type->array.element_type;
|
||||||
for (auto value : values)
|
for (auto value : values)
|
||||||
{
|
{
|
||||||
analyze_type(module, value, element_type, must_be_constant);
|
analyze_type(module, value, element_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
is_constant = is_constant && value->is_constant();
|
is_constant = is_constant && value->is_constant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3169,7 +3219,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
for (auto value : values)
|
for (auto value : values)
|
||||||
{
|
{
|
||||||
analyze_type(module, value, expected_type, must_be_constant);
|
analyze_type(module, value, expected_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
is_constant = is_constant && value->is_constant();
|
is_constant = is_constant && value->is_constant();
|
||||||
|
|
||||||
@ -3209,7 +3259,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
auto array_like = value->array_expression.array_like;
|
auto array_like = value->array_expression.array_like;
|
||||||
array_like->kind = ValueKind::left;
|
array_like->kind = ValueKind::left;
|
||||||
analyze_type(module, array_like, 0, must_be_constant);
|
analyze_type(module, array_like, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
assert(array_like->kind == ValueKind::left);
|
assert(array_like->kind == ValueKind::left);
|
||||||
auto array_like_type = array_like->type;
|
auto array_like_type = array_like->type;
|
||||||
if (array_like_type->id != TypeId::pointer)
|
if (array_like_type->id != TypeId::pointer)
|
||||||
@ -3218,7 +3268,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
}
|
}
|
||||||
auto pointer_element_type = array_like_type->pointer.element_type;
|
auto pointer_element_type = array_like_type->pointer.element_type;
|
||||||
|
|
||||||
analyze_type(module, value->array_expression.index, pointer_element_type->id == TypeId::enum_array ? pointer_element_type->enum_array.enum_type : uint64(module), must_be_constant);
|
analyze_type(module, value->array_expression.index, 0, { .must_be_constant = analysis.must_be_constant, .is_index = true });
|
||||||
|
|
||||||
Type* element_type = 0;
|
Type* element_type = 0;
|
||||||
switch (pointer_element_type->id)
|
switch (pointer_element_type->id)
|
||||||
@ -3281,7 +3331,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
auto aggregate = value->field_access.aggregate;
|
auto aggregate = value->field_access.aggregate;
|
||||||
auto field_name = value->field_access.field_name;
|
auto field_name = value->field_access.field_name;
|
||||||
analyze_type(module, aggregate, 0, must_be_constant);
|
analyze_type(module, aggregate, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
if (aggregate->kind == ValueKind::right)
|
if (aggregate->kind == ValueKind::right)
|
||||||
{
|
{
|
||||||
@ -3373,6 +3423,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
auto field = fields[i];
|
auto field = fields[i];
|
||||||
value_type = field.type;
|
value_type = field.type;
|
||||||
} break;
|
} break;
|
||||||
|
case TypeId::enum_array:
|
||||||
case TypeId::array:
|
case TypeId::array:
|
||||||
{
|
{
|
||||||
if (!field_name.equal(string_literal("length")))
|
if (!field_name.equal(string_literal("length")))
|
||||||
@ -3391,7 +3442,16 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trap();
|
if (resolved_aggregate_type->id == TypeId::enum_array)
|
||||||
|
{
|
||||||
|
auto enum_type = resolved_aggregate_type->enum_array.enum_type;
|
||||||
|
auto backing_type = enum_type->enumerator.backing_type;
|
||||||
|
value_type = backing_type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TypeId::pointer: report_error(); // Double indirection is not allowed
|
case TypeId::pointer: report_error(); // Double indirection is not allowed
|
||||||
@ -3413,7 +3473,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_type(module, array_like, 0, must_be_constant);
|
analyze_type(module, array_like, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
auto pointer_type = array_like->type;
|
auto pointer_type = array_like->type;
|
||||||
if (pointer_type->id != TypeId::pointer)
|
if (pointer_type->id != TypeId::pointer)
|
||||||
@ -3462,7 +3522,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
{
|
{
|
||||||
if (index)
|
if (index)
|
||||||
{
|
{
|
||||||
analyze_type(module, index, index_type, must_be_constant);
|
analyze_type(module, index, index_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
|
|
||||||
if (index->type->id != TypeId::integer)
|
if (index->type->id != TypeId::integer)
|
||||||
{
|
{
|
||||||
@ -3487,7 +3547,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
} break;
|
} break;
|
||||||
case ValueId::va_arg:
|
case ValueId::va_arg:
|
||||||
{
|
{
|
||||||
analyze_type(module, value->va_arg.va_list, get_pointer_type(module, get_va_list_type(module)), must_be_constant);
|
analyze_type(module, value->va_arg.va_list, get_pointer_type(module, get_va_list_type(module)), { .must_be_constant = analysis.must_be_constant });
|
||||||
value_type = value->va_arg.type;
|
value_type = value->va_arg.type;
|
||||||
typecheck(module, expected_type, value_type);
|
typecheck(module, expected_type, value_type);
|
||||||
} break;
|
} break;
|
||||||
@ -3569,7 +3629,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
auto field = fields[declaration_index];
|
auto field = fields[declaration_index];
|
||||||
auto declaration_type = field.type;
|
auto declaration_type = field.type;
|
||||||
analyze_type(module, value, declaration_type, must_be_constant);
|
analyze_type(module, value, declaration_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
is_constant = is_constant && value->is_constant();
|
is_constant = is_constant && value->is_constant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3627,7 +3687,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
auto field = fields[declaration_index];
|
auto field = fields[declaration_index];
|
||||||
auto declaration_type = field.type;
|
auto declaration_type = field.type;
|
||||||
analyze_type(module, value, declaration_type, must_be_constant);
|
analyze_type(module, value, declaration_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
is_constant = is_constant && value->is_constant();
|
is_constant = is_constant && value->is_constant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3660,7 +3720,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto field = &fields[i];
|
auto field = &fields[i];
|
||||||
analyze_type(module, initialization_value, field->type, must_be_constant);
|
analyze_type(module, initialization_value, field->type, { .must_be_constant = analysis.must_be_constant });
|
||||||
} break;
|
} break;
|
||||||
case TypeId::enum_array:
|
case TypeId::enum_array:
|
||||||
{
|
{
|
||||||
@ -3719,7 +3779,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
is_ordered = is_ordered && declaration_index == initialization_index;
|
is_ordered = is_ordered && declaration_index == initialization_index;
|
||||||
|
|
||||||
analyze_type(module, value, element_type, must_be_constant);
|
analyze_type(module, value, element_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
is_constant = is_constant && value->is_constant();
|
is_constant = is_constant && value->is_constant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3747,9 +3807,9 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
auto condition = value->select.condition;
|
auto condition = value->select.condition;
|
||||||
auto true_value = value->select.true_value;
|
auto true_value = value->select.true_value;
|
||||||
auto false_value = value->select.false_value;
|
auto false_value = value->select.false_value;
|
||||||
analyze_type(module, condition, 0, must_be_constant);
|
analyze_type(module, condition, 0, { .must_be_constant = analysis.must_be_constant });
|
||||||
auto is_boolean = false;
|
auto is_boolean = false;
|
||||||
analyze_binary_type(module, true_value, false_value, is_boolean, expected_type, must_be_constant);
|
analyze_binary_type(module, true_value, false_value, is_boolean, expected_type, analysis.must_be_constant);
|
||||||
|
|
||||||
auto left_type = true_value->type;
|
auto left_type = true_value->type;
|
||||||
auto right_type = false_value->type;
|
auto right_type = false_value->type;
|
||||||
@ -4081,7 +4141,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
auto string_type = get_slice_type(module, uint8(module));
|
auto string_type = get_slice_type(module, uint8(module));
|
||||||
|
|
||||||
analyze_type(module, enum_string_value, string_type, must_be_constant);
|
analyze_type(module, enum_string_value, string_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
value_type = struct_type;
|
value_type = struct_type;
|
||||||
} break;
|
} break;
|
||||||
case ValueId::undefined:
|
case ValueId::undefined:
|
||||||
@ -4219,7 +4279,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
auto argument_type = declaration_argument.variable.type;
|
auto argument_type = declaration_argument.variable.type;
|
||||||
assert(argument_type);
|
assert(argument_type);
|
||||||
analyze_type(module, instantiation_argument, argument_type, must_be_constant);
|
analyze_type(module, instantiation_argument, argument_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMMetadataRef type_buffer[64];
|
LLVMMetadataRef type_buffer[64];
|
||||||
@ -4263,7 +4323,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, bool mus
|
|||||||
|
|
||||||
auto argument_type = declaration_argument.variable.type;
|
auto argument_type = declaration_argument.variable.type;
|
||||||
assert(argument_type);
|
assert(argument_type);
|
||||||
analyze_type(module, instantiation_argument, argument_type, must_be_constant);
|
analyze_type(module, instantiation_argument, argument_type, { .must_be_constant = analysis.must_be_constant });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4918,7 +4978,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
{
|
{
|
||||||
src->type = 0;
|
src->type = 0;
|
||||||
src->kind = ValueKind::left;
|
src->kind = ValueKind::left;
|
||||||
analyze_type(module, src, 0, false);
|
analyze_type(module, src, 0, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5066,7 +5126,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
assert(src->kind == ValueKind::right);
|
assert(src->kind == ValueKind::right);
|
||||||
src->type = 0;
|
src->type = 0;
|
||||||
src->kind = ValueKind::left;
|
src->kind = ValueKind::left;
|
||||||
analyze_type(module, src, pointer_type, false);
|
analyze_type(module, src, pointer_type, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -5771,11 +5831,31 @@ fn LLVMValueRef emit_field_access(Module* module, Value* value, LLVMValueRef lef
|
|||||||
|
|
||||||
return trunc;
|
return trunc;
|
||||||
} break;
|
} break;
|
||||||
|
case TypeId::enum_array:
|
||||||
case TypeId::array:
|
case TypeId::array:
|
||||||
{
|
{
|
||||||
assert(value->field_access.field_name.equal(string_literal("length")));
|
assert(value->field_access.field_name.equal(string_literal("length")));
|
||||||
auto array_length_type = get_llvm_type(value->type, type_kind);
|
auto array_length_type = get_llvm_type(value->type, type_kind);
|
||||||
auto result = LLVMConstInt(array_length_type, resolved_aggregate_type->array.element_count, false);
|
u64 array_element_count = 0;
|
||||||
|
|
||||||
|
switch (resolved_aggregate_type->id)
|
||||||
|
{
|
||||||
|
case TypeId::enum_array:
|
||||||
|
{
|
||||||
|
auto enum_type = resolved_aggregate_type->enum_array.enum_type;
|
||||||
|
assert(enum_type->id == TypeId::enumerator);
|
||||||
|
array_element_count = enum_type->enumerator.fields.length;
|
||||||
|
} break;
|
||||||
|
case TypeId::array:
|
||||||
|
{
|
||||||
|
array_element_count = resolved_aggregate_type->array.element_count;
|
||||||
|
} break;
|
||||||
|
default: unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(array_element_count);
|
||||||
|
|
||||||
|
auto result = LLVMConstInt(array_length_type, array_element_count, false);
|
||||||
return result;
|
return result;
|
||||||
} break;
|
} break;
|
||||||
default: unreachable();
|
default: unreachable();
|
||||||
@ -6619,6 +6699,10 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
|||||||
{
|
{
|
||||||
llvm_value = LLVMBuildIntToPtr(module->llvm.builder, llvm_unary_value, resolved_value_type->llvm.abi, "");
|
llvm_value = LLVMBuildIntToPtr(module->llvm.builder, llvm_unary_value, resolved_value_type->llvm.abi, "");
|
||||||
} break;
|
} break;
|
||||||
|
case UnaryId::enum_from_int:
|
||||||
|
{
|
||||||
|
llvm_value = llvm_unary_value;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case ValueId::unary_type:
|
case ValueId::unary_type:
|
||||||
@ -7375,7 +7459,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
|||||||
|
|
||||||
fn void analyze_value(Module* module, Value* value, Type* expected_type, TypeKind type_kind, bool must_be_constant)
|
fn void analyze_value(Module* module, Value* value, Type* expected_type, TypeKind type_kind, bool must_be_constant)
|
||||||
{
|
{
|
||||||
analyze_type(module, value, expected_type, must_be_constant);
|
analyze_type(module, value, expected_type, { .must_be_constant = must_be_constant });
|
||||||
emit_value(module, value, type_kind, must_be_constant);
|
emit_value(module, value, type_kind, must_be_constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7453,7 +7537,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_type(module, return_value, return_abi.semantic_type, false);
|
analyze_type(module, return_value, return_abi.semantic_type, {});
|
||||||
auto pointer_type = get_pointer_type(module, return_abi.semantic_type);
|
auto pointer_type = get_pointer_type(module, return_abi.semantic_type);
|
||||||
emit_assignment(module, return_alloca, pointer_type, return_value);
|
emit_assignment(module, return_alloca, pointer_type, return_value);
|
||||||
} break;
|
} break;
|
||||||
@ -7468,7 +7552,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
auto macro_instantiation = module->current_macro_instantiation;
|
auto macro_instantiation = module->current_macro_instantiation;
|
||||||
auto return_type = macro_instantiation->return_type;
|
auto return_type = macro_instantiation->return_type;
|
||||||
assert(return_type);
|
assert(return_type);
|
||||||
analyze_type(module, return_value, return_type, false);
|
analyze_type(module, return_value, return_type, {});
|
||||||
emit_assignment(module, macro_instantiation->return_alloca, get_pointer_type(module, return_type), return_value);
|
emit_assignment(module, macro_instantiation->return_alloca, get_pointer_type(module, return_type), return_value);
|
||||||
LLVMBuildBr(module->llvm.builder, macro_instantiation->return_block);
|
LLVMBuildBr(module->llvm.builder, macro_instantiation->return_block);
|
||||||
LLVMClearInsertionPosition(module->llvm.builder);
|
LLVMClearInsertionPosition(module->llvm.builder);
|
||||||
@ -7483,7 +7567,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
auto local = statement->local;
|
auto local = statement->local;
|
||||||
auto expected_type = local->variable.type;
|
auto expected_type = local->variable.type;
|
||||||
assert(!local->variable.storage);
|
assert(!local->variable.storage);
|
||||||
analyze_type(module, local->variable.initial_value, expected_type, false);
|
analyze_type(module, local->variable.initial_value, expected_type, {});
|
||||||
local->variable.type = expected_type ? expected_type : local->variable.initial_value->type;
|
local->variable.type = expected_type ? expected_type : local->variable.initial_value->type;
|
||||||
assert(local->variable.type);
|
assert(local->variable.type);
|
||||||
if (expected_type)
|
if (expected_type)
|
||||||
@ -7624,7 +7708,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
{
|
{
|
||||||
case StatementAssignmentId::assign:
|
case StatementAssignmentId::assign:
|
||||||
{
|
{
|
||||||
analyze_type(module, right, element_type, false);
|
analyze_type(module, right, element_type, {});
|
||||||
emit_assignment(module, left_llvm, left_type, right);
|
emit_assignment(module, left_llvm, left_type, right);
|
||||||
} break;
|
} break;
|
||||||
case StatementAssignmentId::assign_add:
|
case StatementAssignmentId::assign_add:
|
||||||
@ -7875,7 +7959,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
auto kind = left_values[i];
|
auto kind = left_values[i];
|
||||||
auto right = right_values[i];
|
auto right = right_values[i];
|
||||||
|
|
||||||
analyze_type(module, right, 0, false);
|
analyze_type(module, right, 0, {});
|
||||||
|
|
||||||
Type* aggregate_type = 0;
|
Type* aggregate_type = 0;
|
||||||
|
|
||||||
@ -8178,7 +8262,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
analyze_type(module, end, 0, false);
|
analyze_type(module, end, 0, {});
|
||||||
auto end_type = end->type;
|
auto end_type = end->type;
|
||||||
assert(end_type);
|
assert(end_type);
|
||||||
start->type = end_type;
|
start->type = end_type;
|
||||||
@ -8195,7 +8279,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
{
|
{
|
||||||
if (!right->type)
|
if (!right->type)
|
||||||
{
|
{
|
||||||
analyze_type(module, right, local_type, false);
|
analyze_type(module, right, local_type, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ enum class ValueIntrinsic
|
|||||||
{
|
{
|
||||||
align_of,
|
align_of,
|
||||||
byte_size,
|
byte_size,
|
||||||
|
enum_from_int,
|
||||||
enum_name,
|
enum_name,
|
||||||
extend,
|
extend,
|
||||||
integer_max,
|
integer_max,
|
||||||
@ -855,6 +856,7 @@ fn Token tokenize(Module* module)
|
|||||||
String value_intrinsics[] = {
|
String value_intrinsics[] = {
|
||||||
string_literal("align_of"),
|
string_literal("align_of"),
|
||||||
string_literal("byte_size"),
|
string_literal("byte_size"),
|
||||||
|
string_literal("enum_from_int"),
|
||||||
string_literal("enum_name"),
|
string_literal("enum_name"),
|
||||||
string_literal("extend"),
|
string_literal("extend"),
|
||||||
string_literal("integer_max"),
|
string_literal("integer_max"),
|
||||||
@ -1363,6 +1365,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
|||||||
|
|
||||||
switch (intrinsic)
|
switch (intrinsic)
|
||||||
{
|
{
|
||||||
|
case ValueIntrinsic::enum_from_int:
|
||||||
case ValueIntrinsic::enum_name:
|
case ValueIntrinsic::enum_name:
|
||||||
case ValueIntrinsic::extend:
|
case ValueIntrinsic::extend:
|
||||||
case ValueIntrinsic::int_from_enum:
|
case ValueIntrinsic::int_from_enum:
|
||||||
@ -1375,6 +1378,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
|||||||
UnaryId id;
|
UnaryId id;
|
||||||
switch (intrinsic)
|
switch (intrinsic)
|
||||||
{
|
{
|
||||||
|
case ValueIntrinsic::enum_from_int: id = UnaryId::enum_from_int; break;
|
||||||
case ValueIntrinsic::enum_name: id = UnaryId::enum_name; break;
|
case ValueIntrinsic::enum_name: id = UnaryId::enum_name; break;
|
||||||
case ValueIntrinsic::extend: id = UnaryId::extend; break;
|
case ValueIntrinsic::extend: id = UnaryId::extend; break;
|
||||||
case ValueIntrinsic::int_from_enum: id = UnaryId::int_from_enum; break;
|
case ValueIntrinsic::int_from_enum: id = UnaryId::int_from_enum; break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user