This commit is contained in:
David Gonzalez Martin 2025-04-19 20:47:54 -06:00
parent c7c5b509f2
commit cdd5342976
3 changed files with 341 additions and 143 deletions

View File

@ -207,6 +207,8 @@ pub const ResolvedType = struct {
pub const Enumerator = struct {
fields: []const Enumerator.Field,
string_to_enum: ?StringToEnum = null,
enum_to_string: ?*llvm.Function = null,
name_array_global: ?*Global = null,
backing_type: *Type,
line: u32,
implicit_backing_type: bool,
@ -813,6 +815,7 @@ pub const Value = struct {
const Intrinsic = union(Id) {
byte_size: *Type,
enum_name: *Value,
extend: *Value,
integer_max: *Type,
int_from_enum: *Value,
@ -829,6 +832,7 @@ pub const Value = struct {
const Id = enum {
byte_size,
enum_name,
extend,
integer_max,
int_from_enum,
@ -1469,26 +1473,7 @@ pub const Module = struct {
});
break :blk array_type;
},
else => b: {
const all_types = module.types.get_slice();
const array_type = for (module.array_types.get_slice()) |array_type_index| {
const array_type = &all_types[array_type_index];
assert(array_type.bb == .array);
if (array_type.bb.array.element_count == element_count and array_type.bb.array.element_type == element_type) {
break array_type;
}
} else module.types.append(.{
.name = array_type_name(module.arena, element_type, element_count),
.bb = .{
.array = .{
.element_type = element_type,
.element_count = element_count,
},
},
});
break :b array_type;
},
else => module.get_array_type(element_type, element_count),
};
return array_type;
@ -1512,6 +1497,27 @@ pub const Module = struct {
}
}
pub fn get_array_type(module: *Module, element_type: *Type, element_count: u64) *Type {
const all_types = module.types.get_slice();
const array_type = for (module.array_types.get_slice()) |array_type_index| {
const array_type = &all_types[array_type_index];
assert(array_type.bb == .array);
if (array_type.bb.array.element_count == element_count and array_type.bb.array.element_type == element_type) {
break array_type;
}
} else module.types.append(.{
.name = array_type_name(module.arena, element_type, element_count),
.bb = .{
.array = .{
.element_type = element_type,
.element_count = element_count,
},
},
});
return array_type;
}
const Slice = struct {
type: *Type,
alignment: ?u32 = null,
@ -2944,6 +2950,20 @@ pub const Module = struct {
},
};
},
.enum_name => blk: {
module.skip_space();
module.expect_character(left_parenthesis);
module.skip_space();
const arg_value = module.parse_value(function, scope, .{});
module.expect_character(right_parenthesis);
break :blk .{
.bb = .{
.intrinsic = .{
.enum_name = arg_value,
},
},
};
},
.extend => blk: {
module.skip_space();
module.expect_character(left_parenthesis);
@ -5483,6 +5503,87 @@ pub const Module = struct {
break :blk expected_type;
},
.enum_name => |enum_value| blk: {
const string_type = module.get_slice_type(.{ .type = module.integer_type(8, false) });
module.typecheck(analysis, string_type);
module.analyze_value_type(function, enum_value, .{});
const enum_type = enum_value.type.?;
switch (enum_type.bb) {
.enumerator => |*enumerator| {
const enum_array_name_global = module.get_enum_name_array_global(enum_value.type.?);
if (enumerator.enum_to_string == null) {
const current_block = module.llvm.builder.get_insert_block();
const llvm_function_type = llvm.Type.Function.get(string_type.llvm.memory.?, &.{ enum_type.llvm.abi.? }, false);
const llvm_function_value = module.llvm.module.create_function(.{
.name = module.arena.join_string(&.{ "enum_to_string.", enum_type.name }),
.linkage = .InternalLinkage,
.type = llvm_function_type,
});
llvm_function_value.set_calling_convention(.fast);
var llvm_function_arguments: [1]*llvm.Argument = undefined;
llvm_function_value.get_arguments(&llvm_function_arguments);
const llvm_arg = llvm_function_arguments[0];
const function_entry_block = module.llvm.context.create_basic_block("entry", llvm_function_value);
module.llvm.builder.position_at_end(function_entry_block);
const alloca = module.create_alloca(.{
.type = string_type,
.name = "retval",
});
const return_block = module.llvm.context.create_basic_block("return_block", llvm_function_value);
const else_block = module.llvm.context.create_basic_block("else_block", llvm_function_value);
const switch_i = module.llvm.builder.create_switch(llvm_arg.to_value(), else_block, @intCast(enumerator.fields.len));
const backing_type = enumerator.backing_type.llvm.abi.?.to_integer();
const uint64 = module.integer_type(64, false).llvm.abi.?.to_integer();
for (enumerator.fields, 0..) |field, field_index| {
const case_block = module.llvm.context.create_basic_block(module.arena.join_string(&.{"case_block.", field.name}), llvm_function_value);
const case_value = backing_type.get_constant(field.value, 0).to_value();
switch_i.add_case(case_value, case_block);
module.llvm.builder.position_at_end(case_block);
const case_value_result_pointer = module.llvm.builder.create_gep(.{
.type = enum_array_name_global.variable.type.?.llvm.memory.?,
.aggregate = enum_array_name_global.variable.storage.?.llvm.?,
.indices = &.{uint64.get_constant(0, 0).to_value(), uint64.get_constant(field_index, 0).to_value() },
});
const case_value_result = module.create_load(.{
.type = string_type,
.value = case_value_result_pointer,
});
_ = module.create_store(.{
.type = string_type,
.destination_value = alloca,
.source_value = case_value_result,
});
_ = module.llvm.builder.create_branch(return_block);
}
module.llvm.builder.position_at_end(else_block);
_ = module.llvm.builder.create_unreachable();
module.llvm.builder.position_at_end(return_block);
const function_result = module.create_load(.{
.type = string_type,
.value = alloca,
});
module.llvm.builder.create_ret(function_result);
if (current_block) |bb| {
module.llvm.builder.position_at_end(bb);
}
enumerator.enum_to_string = llvm_function_value;
}
break :blk string_type;
},
else => module.report_error(),
}
},
.extend => |extended_value| blk: {
const expected_type = analysis.type orelse module.report_error();
module.analyze_value_type(function, extended_value, .{});
@ -5622,6 +5723,7 @@ pub const Module = struct {
uint64.resolve(module);
const llvm_function_type = llvm.Type.Function.get(struct_type.llvm.abi.?, &.{ module.llvm.pointer_type, uint64.llvm.abi.? }, false);
const slice_struct_type = module.get_slice_type(.{ .type = uint8 });
_ = slice_struct_type;
const llvm_function_value = module.llvm.module.create_function(.{
.name = module.arena.join_string(&.{ "string_to_enum.", string_to_enum.enum_type.name }),
@ -5630,30 +5732,12 @@ pub const Module = struct {
});
llvm_function_value.set_calling_convention(.fast);
var name_before: ?*llvm.GlobalVariable = null;
var value_constant_buffer: [64]*llvm.Constant = undefined;
var name_constant_buffer: [64]*llvm.Constant = undefined;
for (string_to_enum.enum_type.bb.enumerator.fields, 0..) |field, field_index| {
const value_global = string_to_enum.enum_type.llvm.memory.?.to_integer().get_constant(field.value, 0);
value_constant_buffer[field_index] = value_global.to_constant();
const null_terminate = true;
const name_global = module.llvm.module.create_global_variable(.{
.type = uint8.llvm.abi.?.get_array_type(field.name.len + @intFromBool(null_terminate)).to_type(),
.linkage = .InternalLinkage,
.name = module.arena.join_string(&.{ "string.", string_to_enum.enum_type.name, ".", field.name }),
.initial_value = module.llvm.context.get_constant_string(field.name, null_terminate),
.is_constant = true,
.before = name_before,
});
name_before = name_global;
const slice_constant = module.llvm.context.get_anonymous_constant_struct(&.{
name_global.to_constant(),
uint64.llvm.abi.?.to_integer().get_constant(field.name.len, 0).to_constant(),
}, false);
name_constant_buffer[field_index] = slice_constant;
}
const value_array = string_to_enum.enum_type.llvm.memory.?.get_constant_array(value_constant_buffer[0..array_element_count]);
@ -5666,18 +5750,9 @@ pub const Module = struct {
});
value_array_variable.to_value().set_alignment(string_to_enum.enum_type.get_byte_alignment());
const name_array = slice_struct_type.llvm.abi.?.get_constant_array(name_constant_buffer[0..array_element_count]);
const name_array_variable_type = slice_struct_type.llvm.abi.?.get_array_type(array_element_count);
const name_array_variable = module.llvm.module.create_global_variable(.{
.type = name_array_variable_type.to_type(),
.linkage = .InternalLinkage,
.initial_value = name_array,
.name = "name.array.enum",
});
name_array_variable.to_value().set_alignment(slice_struct_type.get_byte_alignment());
const function_entry_block = module.llvm.context.create_basic_block("entry", llvm_function_value);
const return_block = module.llvm.context.create_basic_block("return_block", llvm_function_value);
_ = return_block;
const loop_entry_block = module.llvm.context.create_basic_block("loop.entry", llvm_function_value);
const loop_body_block = module.llvm.context.create_basic_block("loop.body", llvm_function_value);
const loop_exit_block = module.llvm.context.create_basic_block("loop.exit", llvm_function_value);
@ -5696,6 +5771,8 @@ pub const Module = struct {
s.set_alignment(8);
const slice_pointer = arguments[0].to_value();
const slice_length = arguments[1].to_value();
_ = slice_pointer;
_ = slice_length;
_ = module.llvm.builder.create_branch(loop_entry_block);
module.llvm.builder.position_at_end(loop_entry_block);
@ -5709,102 +5786,107 @@ pub const Module = struct {
const body_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
body_index_load.set_alignment(8);
const uint64_zero = uint64.llvm.abi.?.get_zero().to_value();
const array_element_pointer = module.llvm.builder.create_gep(.{
.type = name_array_variable_type.to_type(),
.aggregate = name_array_variable.to_value(),
.indices = &.{ uint64_zero, body_index_load },
});
_ = uint64_zero;
const element_length_pointer = module.llvm.builder.create_struct_gep(slice_struct_type.llvm.abi.?.to_struct(), array_element_pointer, 1);
const element_length = module.llvm.builder.create_load(uint64.llvm.abi.?, element_length_pointer);
element_length.set_alignment(8);
const length_comparison = module.llvm.builder.create_integer_compare(.eq, slice_length, element_length);
const length_match_block = module.llvm.context.create_basic_block("length.match", llvm_function_value);
const length_mismatch_block = module.llvm.context.create_basic_block("length.mismatch", llvm_function_value);
_ = module.llvm.builder.create_conditional_branch(length_comparison, length_match_block, length_mismatch_block);
module.llvm.builder.position_at_end(length_match_block);
const s32 = module.integer_type(32, true);
s32.resolve(module);
const memcmp = if (module.llvm.memcmp) |memcmp| memcmp else b: {
if (module.llvm.module.get_named_function("memcmp")) |memcmp| {
module.llvm.memcmp = memcmp;
break :b memcmp;
} else {
const memcmp = module.llvm.module.create_function(.{
.name = "memcmp",
.linkage = .ExternalLinkage,
.type = llvm.Type.Function.get(s32.llvm.abi.?, &.{ module.llvm.pointer_type, module.llvm.pointer_type, uint64.llvm.abi.? }, false),
});
module.llvm.memcmp = memcmp;
break :b memcmp;
}
};
const length_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
const length_array_element_pointer = module.llvm.builder.create_gep(.{
.type = name_array_variable_type.to_type(),
.aggregate = name_array_variable.to_value(),
.indices = &.{ uint64_zero, length_index_load },
});
const element_pointer_pointer = module.llvm.builder.create_struct_gep(slice_struct_type.llvm.abi.?.to_struct(), length_array_element_pointer, 0);
const element_pointer = module.llvm.builder.create_load(module.llvm.pointer_type, element_pointer_pointer);
element_pointer.set_alignment(8);
const memcmp_return_result = module.llvm.builder.create_call(memcmp.get_type(), memcmp.to_value(), &.{ slice_pointer, element_pointer, slice_length });
const content_comparison = module.llvm.builder.create_integer_compare(.eq, memcmp_return_result, s32.llvm.abi.?.get_zero().to_value());
const content_match_block = module.llvm.context.create_basic_block("content.match", llvm_function_value);
_ = module.llvm.builder.create_conditional_branch(content_comparison, content_match_block, length_mismatch_block);
module.llvm.builder.position_at_end(content_match_block);
const content_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
content_index_load.set_alignment(8);
const value_array_element_pointer = module.llvm.builder.create_gep(.{
.type = value_array_variable_type.to_type(),
.aggregate = value_array_variable.to_value(),
.indices = &.{ uint64_zero, content_index_load },
});
const enum_value_load = module.llvm.builder.create_load(string_to_enum.enum_type.llvm.memory.?, value_array_element_pointer);
enum_value_load.set_alignment(string_to_enum.enum_type.get_byte_alignment());
const s1 = module.llvm.builder.create_store(enum_value_load, return_value_alloca);
s1.set_alignment(string_to_enum.enum_type.get_byte_alignment());
const s2 = module.llvm.builder.create_store(uint8.llvm.abi.?.to_integer().get_constant(1, 0).to_value(), return_boolean_alloca);
s2.set_alignment(uint8.get_byte_alignment());
_ = module.llvm.builder.create_branch(return_block);
module.llvm.builder.position_at_end(length_mismatch_block);
const inc_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
inc_index_load.set_alignment(8);
const inc = module.llvm.builder.create_add(inc_index_load, uint64.llvm.abi.?.to_integer().get_constant(1, 0).to_value());
const s3 = module.llvm.builder.create_store(inc, index_alloca);
s3.set_alignment(8);
_ = module.llvm.builder.create_branch(loop_entry_block);
module.llvm.builder.position_at_end(loop_exit_block);
const s4 = module.llvm.builder.create_store(string_to_enum.enum_type.llvm.memory.?.get_zero().to_value(), return_value_alloca);
s4.set_alignment(struct_type.get_byte_alignment());
const s5 = module.llvm.builder.create_store(uint8.llvm.memory.?.get_zero().to_value(), return_boolean_alloca);
s5.set_alignment(uint8.get_byte_alignment());
_ = module.llvm.builder.create_branch(return_block);
module.llvm.builder.position_at_end(return_block);
const value_load = module.llvm.builder.create_load(string_to_enum.enum_type.llvm.memory.?, return_value_alloca);
value_load.set_alignment(string_to_enum.enum_type.get_byte_alignment());
var return_value = module.llvm.builder.create_insert_value(struct_type.llvm.memory.?.get_poison(), value_load, 0);
const bool_load = module.llvm.builder.create_load(uint8.llvm.abi.?, return_boolean_alloca);
bool_load.set_alignment(1);
return_value = module.llvm.builder.create_insert_value(return_value, bool_load, 1);
module.llvm.builder.create_ret(return_value);
string_to_enum.enum_type.bb.enumerator.string_to_enum = .{
.function = llvm_function_value,
.struct_type = struct_type,
};
@trap();
}
// const array_element_pointer = module.llvm.builder.create_gep(.{
// .type = name_array_variable_type.to_type(),
// .aggregate = name_array_variable.to_value(),
// .indices = &.{ uint64_zero, body_index_load },
// });
//
// const element_length_pointer = module.llvm.builder.create_struct_gep(slice_struct_type.llvm.abi.?.to_struct(), array_element_pointer, 1);
// const element_length = module.llvm.builder.create_load(uint64.llvm.abi.?, element_length_pointer);
// element_length.set_alignment(8);
//
// const length_comparison = module.llvm.builder.create_integer_compare(.eq, slice_length, element_length);
//
// const length_match_block = module.llvm.context.create_basic_block("length.match", llvm_function_value);
// const length_mismatch_block = module.llvm.context.create_basic_block("length.mismatch", llvm_function_value);
// _ = module.llvm.builder.create_conditional_branch(length_comparison, length_match_block, length_mismatch_block);
//
// module.llvm.builder.position_at_end(length_match_block);
// const s32 = module.integer_type(32, true);
// s32.resolve(module);
// const memcmp = if (module.llvm.memcmp) |memcmp| memcmp else b: {
// if (module.llvm.module.get_named_function("memcmp")) |memcmp| {
// module.llvm.memcmp = memcmp;
// break :b memcmp;
// } else {
// const memcmp = module.llvm.module.create_function(.{
// .name = "memcmp",
// .linkage = .ExternalLinkage,
// .type = llvm.Type.Function.get(s32.llvm.abi.?, &.{ module.llvm.pointer_type, module.llvm.pointer_type, uint64.llvm.abi.? }, false),
// });
// module.llvm.memcmp = memcmp;
// break :b memcmp;
// }
// };
//
// const length_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
// const length_array_element_pointer = module.llvm.builder.create_gep(.{
// .type = name_array_variable_type.to_type(),
// .aggregate = name_array_variable.to_value(),
// .indices = &.{ uint64_zero, length_index_load },
// });
// const element_pointer_pointer = module.llvm.builder.create_struct_gep(slice_struct_type.llvm.abi.?.to_struct(), length_array_element_pointer, 0);
// const element_pointer = module.llvm.builder.create_load(module.llvm.pointer_type, element_pointer_pointer);
// element_pointer.set_alignment(8);
// const memcmp_return_result = module.llvm.builder.create_call(memcmp.get_type(), memcmp.to_value(), &.{ slice_pointer, element_pointer, slice_length });
// const content_comparison = module.llvm.builder.create_integer_compare(.eq, memcmp_return_result, s32.llvm.abi.?.get_zero().to_value());
// const content_match_block = module.llvm.context.create_basic_block("content.match", llvm_function_value);
// _ = module.llvm.builder.create_conditional_branch(content_comparison, content_match_block, length_mismatch_block);
//
// module.llvm.builder.position_at_end(content_match_block);
// const content_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
// content_index_load.set_alignment(8);
// const value_array_element_pointer = module.llvm.builder.create_gep(.{
// .type = value_array_variable_type.to_type(),
// .aggregate = value_array_variable.to_value(),
// .indices = &.{ uint64_zero, content_index_load },
// });
// const enum_value_load = module.llvm.builder.create_load(string_to_enum.enum_type.llvm.memory.?, value_array_element_pointer);
// enum_value_load.set_alignment(string_to_enum.enum_type.get_byte_alignment());
// const s1 = module.llvm.builder.create_store(enum_value_load, return_value_alloca);
// s1.set_alignment(string_to_enum.enum_type.get_byte_alignment());
// const s2 = module.llvm.builder.create_store(uint8.llvm.abi.?.to_integer().get_constant(1, 0).to_value(), return_boolean_alloca);
// s2.set_alignment(uint8.get_byte_alignment());
// _ = module.llvm.builder.create_branch(return_block);
//
// module.llvm.builder.position_at_end(length_mismatch_block);
// const inc_index_load = module.llvm.builder.create_load(uint64.llvm.abi.?, index_alloca);
// inc_index_load.set_alignment(8);
// const inc = module.llvm.builder.create_add(inc_index_load, uint64.llvm.abi.?.to_integer().get_constant(1, 0).to_value());
// const s3 = module.llvm.builder.create_store(inc, index_alloca);
// s3.set_alignment(8);
// _ = module.llvm.builder.create_branch(loop_entry_block);
//
// module.llvm.builder.position_at_end(loop_exit_block);
// const s4 = module.llvm.builder.create_store(string_to_enum.enum_type.llvm.memory.?.get_zero().to_value(), return_value_alloca);
// s4.set_alignment(struct_type.get_byte_alignment());
// const s5 = module.llvm.builder.create_store(uint8.llvm.memory.?.get_zero().to_value(), return_boolean_alloca);
// s5.set_alignment(uint8.get_byte_alignment());
// _ = module.llvm.builder.create_branch(return_block);
//
// module.llvm.builder.position_at_end(return_block);
//
// const value_load = module.llvm.builder.create_load(string_to_enum.enum_type.llvm.memory.?, return_value_alloca);
// value_load.set_alignment(string_to_enum.enum_type.get_byte_alignment());
// var return_value = module.llvm.builder.create_insert_value(struct_type.llvm.memory.?.get_poison(), value_load, 0);
// const bool_load = module.llvm.builder.create_load(uint8.llvm.abi.?, return_boolean_alloca);
// bool_load.set_alignment(1);
// return_value = module.llvm.builder.create_insert_value(return_value, bool_load, 1);
//
// module.llvm.builder.create_ret(return_value);
//
// string_to_enum.enum_type.bb.enumerator.string_to_enum = .{
// .function = llvm_function_value,
// .struct_type = struct_type,
// };
// }
//
const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable;
const result_type = s2e.struct_type;
@ -6107,6 +6189,79 @@ pub const Module = struct {
value.type = value_type;
}
pub fn get_enum_name_array_global(module: *Module, enum_type: *Type) *Global {
switch (enum_type.bb) {
.enumerator => |*enumerator| {
if (enumerator.name_array_global) |name_array| {
return name_array;
} else {
const fields = enumerator.fields;
var name_before: ?*llvm.GlobalVariable = null;
var name_constant_buffer: [64]*llvm.Constant = undefined;
const uint8 = module.integer_type(8, false);
const uint64 = module.integer_type(64, false);
for (fields, 0..) |field, field_index| {
const null_terminate = true;
const name_global = module.llvm.module.create_global_variable(.{
.type = uint8.llvm.abi.?.get_array_type(field.name.len + @intFromBool(null_terminate)).to_type(),
.linkage = .InternalLinkage,
.name = module.arena.join_string(&.{ "string.", enum_type.name, ".", field.name }),
.initial_value = module.llvm.context.get_constant_string(field.name, null_terminate),
.is_constant = true,
.before = name_before,
});
name_before = name_global;
const slice_constant = module.llvm.context.get_anonymous_constant_struct(&.{
name_global.to_constant(),
uint64.llvm.abi.?.to_integer().get_constant(field.name.len, 0).to_constant(),
}, false);
name_constant_buffer[field_index] = slice_constant;
}
const slice_struct_type = module.get_slice_type(.{ .type = uint8 });
const array_element_count = fields.len;
const name_array = slice_struct_type.llvm.abi.?.get_constant_array(name_constant_buffer[0..array_element_count]);
const name_array_variable_type = slice_struct_type.llvm.abi.?.get_array_type(array_element_count);
const name_array_variable = module.llvm.module.create_global_variable(.{
.type = name_array_variable_type.to_type(),
.linkage = .InternalLinkage,
.initial_value = name_array,
.name = "name.array.enum",
});
name_array_variable.to_value().set_alignment(slice_struct_type.get_byte_alignment());
const global_type = module.get_array_type(slice_struct_type, array_element_count);
const storage_type = module.get_pointer_type(.{ .type = global_type });
storage_type.resolve(module);
const global_storage = module.values.add();
global_storage.* = .{
.bb = .global,
.type = storage_type,
.llvm = name_array_variable.to_value(),
.kind = .left,
};
const global = module.globals.add();
global.* = .{
.variable = .{
.storage = global_storage,
.initial_value = undefined,
.type = global_type,
.scope = &module.scope,
.name = module.arena.join_string(&.{"name.array.enum.", enum_type.name }),
.line = 0,
.column = 0,
},
.linkage = .internal,
};
enumerator.name_array_global = global;
return global;
}
},
else => unreachable,
}
}
pub fn emit_slice_expression(module: *Module, function: ?*Global, value: *Value) struct { *llvm.Value, *llvm.Value } {
const value_type = value.type.?;
assert(value_type.is_slice());
@ -6299,11 +6454,13 @@ pub const Module = struct {
_ = module.llvm.builder.create_branch(end_block);
module.llvm.builder.position_at_end(end_block);
const boolean_type = module.integer_type(1, false).llvm.abi.?;
const phi = module.llvm.builder.create_phi(boolean_type);
phi.add_incoming(&.{ switch (op) {
.@"and" => boolean_type.get_zero().to_value(),
.@"or" => boolean_type.to_integer().get_constant(1, 0).to_value(),
}, right_condition }, &.{ current_bb, right_block });
break :blk switch (type_kind) {
.abi => phi.to_value(),
.memory => @trap(),
@ -6426,6 +6583,14 @@ pub const Module = struct {
const constant_integer = value_type.llvm.abi.?.to_integer().get_constant(byte_size, @intFromBool(false));
break :blk constant_integer.to_value();
},
.enum_name => |enum_value| blk: {
const enum_type = enum_value.type.?;
const enum_to_string = enum_type.bb.enumerator.enum_to_string.?;
module.emit_value(function, enum_value, .abi);
const call = module.llvm.builder.create_call(enum_to_string.get_type(), enum_to_string.to_value(), &.{enum_value.llvm.?});
call.to_instruction().to_call_base().set_calling_convention(.fast);
break :blk call;
},
.extend => |extended_value| blk: {
if (extended_value.llvm == null) {
module.emit_value(function, extended_value, type_kind);

View File

@ -277,7 +277,7 @@ arena_join_string = fn (arena: &Arena, pieces: [][]u8) []u8
assert(i == size);
pointer[i] = 0;
return pointer[0..size];
return pointer[..size];
}
GlobalState = struct
@ -325,6 +325,8 @@ CompileFile = struct
silent: u1,
}
base_cache_dir = "bb-cache";
compile_file = fn (arena: &Arena, compile: CompileFile) void
{
>relative_file_path = compile.relative_file_path;
@ -354,6 +356,13 @@ compile_file = fn (arena: &Arena, compile: CompileFile) void
>base_name = relative_file_path[base_start..extension_start];
>is_compiler = string_equal(relative_file_path, "src/compiler.bbb");
>outputh_path_dir = arena_join_string(arena, [
base_cache_dir,
#select(is_compiler, "/compiler/", "/"),
#enum_name(compile.build_mode),
"_",
#select(compile.has_debug_info, "di", "nodi"),
][..]);
}
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8) s32

24
tests/enum_name.bbb Normal file
View File

@ -0,0 +1,24 @@
E = enum
{
my_expected_result,
a,
b,
}
[extern] memcmp = fn [cc(c)] (a: &u8, b: &u8, byte_count: u64) s32;
string_equal = fn (slice_a: []u8, slice_b: []u8) u1
{
>result = slice_a.length == slice_b.length;
if (result)
{
result = memcmp(slice_a.pointer, slice_b.pointer, slice_a.length) == 0;
}
return result;
}
[export] main = fn [cc(c)] () s32
{
>some_enum: E = .my_expected_result;
return #extend(!string_equal(#enum_name(some_enum), "my_expected_result"));
}