Compile the self-hosted compiler foundations
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 1m31s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 1m30s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 1m38s
CI / ci (Debug, ubuntu-latest) (push) Successful in 2m39s

This commit is contained in:
David Gonzalez Martin 2025-04-14 12:11:21 -06:00
parent eaeaa0f3b2
commit d45414cf1d
2 changed files with 185 additions and 94 deletions

View File

@ -528,6 +528,7 @@ pub const Type = struct {
.bits => |bits| bits.backing_type.get_bit_size(), .bits => |bits| bits.backing_type.get_bit_size(),
.array => |array| array.element_type.get_bit_size() * array.element_count, .array => |array| array.element_type.get_bit_size() * array.element_count,
.structure => |structure| structure.bit_size, .structure => |structure| structure.bit_size,
.enumerator => |enumerator| enumerator.backing_type.get_bit_size(),
else => @trap(), else => @trap(),
}; };
return bit_size; return bit_size;
@ -699,6 +700,7 @@ pub const Value = struct {
zero, zero,
slice_expression: SliceExpression, slice_expression: SliceExpression,
@"unreachable", @"unreachable",
undefined,
}, },
type: ?*Type = null, type: ?*Type = null,
llvm: ?*llvm.Value = null, llvm: ?*llvm.Value = null,
@ -729,8 +731,6 @@ pub const Value = struct {
const Intrinsic = union(Id) { const Intrinsic = union(Id) {
byte_size: *Type, byte_size: *Type,
cast,
cast_to,
extend: *Value, extend: *Value,
integer_max: *Type, integer_max: *Type,
int_from_enum: *Value, int_from_enum: *Value,
@ -746,8 +746,6 @@ pub const Value = struct {
const Id = enum { const Id = enum {
byte_size, byte_size,
cast,
cast_to,
extend, extend,
integer_max, integer_max,
int_from_enum, int_from_enum,
@ -780,7 +778,16 @@ pub const Value = struct {
.variable_reference => false, .variable_reference => false,
.aggregate_initialization => |aggregate_initialization| aggregate_initialization.is_constant, .aggregate_initialization => |aggregate_initialization| aggregate_initialization.is_constant,
.field_access => false, .field_access => false,
.binary => false,
.array_initialization => |array_initialization| array_initialization.is_constant, .array_initialization => |array_initialization| array_initialization.is_constant,
.intrinsic => |intrinsic| switch (intrinsic) {
.byte_size,
.integer_max,
=> true,
else => false,
},
.undefined => true,
.call => false,
else => @trap(), else => @trap(),
}; };
} }
@ -2534,7 +2541,9 @@ pub const Module = struct {
.@"unreachable" => .{ .@"unreachable" => .{
.bb = .@"unreachable", .bb = .@"unreachable",
}, },
else => @trap(), .undefined => .{
.bb = .undefined,
},
}; };
value.* = new_value; value.* = new_value;
return value; return value;
@ -2766,6 +2775,10 @@ pub const Module = struct {
.@">>" => .@">>", .@">>" => .@">>",
.@"==" => .@"==", .@"==" => .@"==",
.@"!=" => .@"!=", .@"!=" => .@"!=",
.@">=" => .@">=",
.@"<=" => .@"<=",
.@">" => .@">",
.@"<" => .@"<",
else => @trap(), else => @trap(),
}; };
@ -3701,7 +3714,7 @@ pub const Module = struct {
module.llvm.builder.position_at_end(block); module.llvm.builder.position_at_end(block);
} }
pub fn emit_va_arg(module: *Module, function: *Global, value: *Value, left: ?*Value) *llvm.Value { pub fn emit_va_arg(module: *Module, function: *Global, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value {
switch (value.bb) { switch (value.bb) {
.intrinsic => |intrinsic| switch (intrinsic) { .intrinsic => |intrinsic| switch (intrinsic) {
.va_arg => |va_arg| { .va_arg => |va_arg| {
@ -3796,9 +3809,9 @@ pub const Module = struct {
}; };
const result = switch (va_arg.type.get_evaluation_kind()) { const result = switch (va_arg.type.get_evaluation_kind()) {
.scalar => module.create_load(.{ .type = va_arg.type, .value = llvm_address }), .scalar => module.create_load(.{ .type = va_arg.type, .value = llvm_address }),
.aggregate => if (left) |l| b: { .aggregate => if (left_llvm) |l| b: {
_ = module.llvm.builder.create_memcpy(l.llvm.?, l.type.?.bb.pointer.alignment, llvm_address, va_arg.type.get_byte_alignment(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(va_arg.type.get_byte_size(), 0).to_value()); _ = module.llvm.builder.create_memcpy(l, left_type.?.bb.pointer.alignment, llvm_address, va_arg.type.get_byte_alignment(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(va_arg.type.get_byte_size(), 0).to_value());
break :b l.llvm.?; break :b l;
} else llvm_address, } else llvm_address,
.complex => @trap(), .complex => @trap(),
}; };
@ -3810,7 +3823,7 @@ pub const Module = struct {
} }
} }
pub fn emit_call(module: *Module, function: *Global, value: *Value, left: ?*Value) *llvm.Value { pub fn emit_call(module: *Module, function: *Global, value: *Value, left_llvm: ?*llvm.Value, left_type: ?*Type) *llvm.Value {
switch (value.bb) { switch (value.bb) {
.call => |call| { .call => |call| {
const raw_function_type = call.function_type; const raw_function_type = call.function_type;
@ -3850,9 +3863,9 @@ pub const Module = struct {
// - virtual function pointer thunk // - virtual function pointer thunk
// - return alloca already exists // - return alloca already exists
const semantic_return_type = function_type.return_abi.semantic_type; const semantic_return_type = function_type.return_abi.semantic_type;
const pointer = if (left) |l| b: { const pointer = if (left_llvm) |l| b: {
assert(l.type.?.bb.pointer.type == semantic_return_type); assert(left_type.?.bb.pointer.type == semantic_return_type);
break :b l.llvm.?; break :b l;
} else b: { } else b: {
const temporal_alloca = module.create_alloca(.{ .type = semantic_return_type, .name = "tmp" }); const temporal_alloca = module.create_alloca(.{ .type = semantic_return_type, .name = "tmp" });
break :b temporal_alloca; break :b temporal_alloca;
@ -4081,8 +4094,7 @@ pub const Module = struct {
if (abi_argument_type == semantic_argument_value.type) { if (abi_argument_type == semantic_argument_value.type) {
@trap(); @trap();
} else if (abi_argument_type.bb == .pointer and abi_argument_type.bb.pointer.type == semantic_argument_value.type) { } else if (abi_argument_type.bb == .pointer and abi_argument_type.bb.pointer.type == semantic_argument_value.type) switch (semantic_argument_value.is_constant()) {
switch (semantic_argument_value.is_constant()) {
true => { true => {
module.emit_value(function, semantic_argument_value); module.emit_value(function, semantic_argument_value);
const global_variable = module.llvm.module.create_global_variable(.{ const global_variable = module.llvm.module.create_global_variable(.{
@ -4098,19 +4110,28 @@ pub const Module = struct {
abi_argument_count += 1; abi_argument_count += 1;
break :indirect; break :indirect;
}, },
false => switch (semantic_argument_value.kind) { false => switch (semantic_argument_value.bb) {
.left => module.report_error(), .variable_reference => {
.right => { const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? });
semantic_argument_value.type = null;
semantic_argument_value.kind = .left; semantic_argument_value.kind = .left;
semantic_argument_value.type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? }); module.analyze(function, semantic_argument_value, .{ .type = pointer_type });
module.emit_value(function, semantic_argument_value);
assert(abi_argument_type == semantic_argument_value.type);
llvm_abi_argument_value_buffer[abi_argument_count] = semantic_argument_value.llvm.?; llvm_abi_argument_value_buffer[abi_argument_count] = semantic_argument_value.llvm.?;
abi_argument_count += 1; abi_argument_count += 1;
break :indirect; break :indirect;
}, },
else => {
assert(abi_argument_type.bb.pointer.type == semantic_argument_value.type);
const alloca = module.create_alloca(.{
.type = semantic_argument_value.type.?,
});
const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? });
module.emit_assignment(function, alloca, pointer_type, semantic_argument_value);
llvm_abi_argument_value_buffer[abi_argument_count] = alloca;
abi_argument_count += 1;
break :indirect;
},
}, },
}
} else { } else {
@trap(); @trap();
} }
@ -4223,9 +4244,9 @@ pub const Module = struct {
@trap(); @trap();
} }
const coerce_alloca = if (left) |l| b: { const coerce_alloca = if (left_llvm) |l| b: {
assert(l.type.?.bb.pointer.type == return_type_abi.semantic_type); assert(left_type.?.bb.pointer.type == return_type_abi.semantic_type);
break :b l.llvm.?; break :b l;
} else module.create_alloca(.{ .type = return_type_abi.semantic_type, .name = "coerce" }); } else module.create_alloca(.{ .type = return_type_abi.semantic_type, .name = "coerce" });
var destination_pointer = switch (return_type_abi.attributes.direct.offset == 0) { var destination_pointer = switch (return_type_abi.attributes.direct.offset == 0) {
true => coerce_alloca, true => coerce_alloca,
@ -4717,6 +4738,15 @@ pub const Module = struct {
}, },
.global => { .global => {
module.analyze(null, global.variable.initial_value, .{ .type = global.variable.type }); module.analyze(null, global.variable.initial_value, .{ .type = global.variable.type });
if (global.variable.type == null) {
global.variable.type = global.variable.initial_value.type;
}
if (global.variable.type != global.variable.initial_value.type) {
module.report_error();
}
const global_variable = module.llvm.module.create_global_variable(.{ const global_variable = module.llvm.module.create_global_variable(.{
.linkage = switch (global.linkage) { .linkage = switch (global.linkage) {
.internal => .InternalLinkage, .internal => .InternalLinkage,
@ -5250,6 +5280,13 @@ pub const Module = struct {
module.report_error(); module.report_error();
} }
}, },
.undefined => {},
.string_literal => {
const slice_type = module.get_slice_type(.{ .type = module.integer_type(8, false) });
if (expected_type != slice_type) {
module.report_error();
}
},
else => @trap(), else => @trap(),
}; };
@ -5761,7 +5798,7 @@ pub const Module = struct {
const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.handle.?); const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.handle.?);
break :blk truncate; break :blk truncate;
}, },
.va_arg => module.emit_va_arg(function.?, value, null), .va_arg => module.emit_va_arg(function.?, value, null, null),
.va_end => |va_list| blk: { .va_end => |va_list| blk: {
module.emit_value(function, va_list); module.emit_value(function, va_list);
@ -5787,7 +5824,7 @@ pub const Module = struct {
}; };
break :blk result; break :blk result;
}, },
.call => module.emit_call(function.?, value, null), .call => module.emit_call(function.?, value, null, null),
.array_initialization => |array_initialization| switch (array_initialization.is_constant) { .array_initialization => |array_initialization| switch (array_initialization.is_constant) {
true => blk: { true => blk: {
var llvm_value_buffer: [64]*llvm.Constant = undefined; var llvm_value_buffer: [64]*llvm.Constant = undefined;
@ -5911,7 +5948,7 @@ pub const Module = struct {
break field.value; break field.value;
} }
} else module.report_error(); } else module.report_error();
const llvm_value = value_type.llvm.handle.?.to_integer().get_constant(enum_int_value, @intFromBool(false)); const llvm_value = value_type.resolve(module).handle.to_integer().get_constant(enum_int_value, @intFromBool(false));
break :blk llvm_value.to_value(); break :blk llvm_value.to_value();
}, },
.field_access => |field_access| blk: { .field_access => |field_access| blk: {
@ -5969,7 +6006,6 @@ pub const Module = struct {
} }
} else unreachable; } else unreachable;
const field = &bits.fields[declaration_index]; const field = &bits.fields[declaration_index];
_ = field.bit_offset;
const fv = switch (field_value.bb) { const fv = switch (field_value.bb) {
.constant_integer => |ci| ci.value, .constant_integer => |ci| ci.value,
@ -5981,15 +6017,30 @@ pub const Module = struct {
const llvm_value = bits.backing_type.resolve(module).handle.to_integer().get_constant(bits_value, @intFromBool(false)); const llvm_value = bits.backing_type.resolve(module).handle.to_integer().get_constant(bits_value, @intFromBool(false));
break :blk llvm_value.to_value(); break :blk llvm_value.to_value();
}, },
false => { false => blk: {
@trap(); const llvm_type = bits.backing_type.resolve(module).handle;
const zero_value = llvm_type.get_zero();
var result = zero_value.to_value();
for (aggregate_initialization.names, aggregate_initialization.values) |field_name, field_value| {
const declaration_index = for (bits.fields, 0..) |field, declaration_index| {
if (lib.string.equal(field_name, field.name)) {
break declaration_index;
}
} else unreachable;
const field = &bits.fields[declaration_index];
module.emit_value(function, field_value);
const extended = module.llvm.builder.create_zero_extend(field_value.llvm.?, llvm_type);
const shl = module.llvm.builder.create_shl(extended, llvm_type.to_integer().get_constant(field.bit_offset, 0).to_value());
const or_value = module.llvm.builder.create_or(result, shl);
result = or_value;
}
break :blk result;
}, },
}, },
.structure => |structure| switch (aggregate_initialization.is_constant) { .structure => |structure| switch (aggregate_initialization.is_constant) {
true => blk: { true => blk: {
var constant_buffer: [64]*llvm.Constant = undefined; var constant_buffer: [64]*llvm.Constant = undefined;
const constants = constant_buffer[0..structure.fields.len]; const constants = constant_buffer[0..structure.fields.len];
_ = &constant_buffer;
for (aggregate_initialization.values, constants[0..aggregate_initialization.values.len]) |field_value, *constant| { for (aggregate_initialization.values, constants[0..aggregate_initialization.values.len]) |field_value, *constant| {
module.emit_value(function, field_value); module.emit_value(function, field_value);
constant.* = field_value.llvm.?.to_constant(); constant.* = field_value.llvm.?.to_constant();
@ -6011,6 +6062,7 @@ pub const Module = struct {
@trap(); @trap();
}, },
}, },
.pointer => module.report_error(),
else => @trap(), else => @trap(),
}, },
.zero => value_type.resolve(module).handle.get_zero().to_value(), .zero => value_type.resolve(module).handle.get_zero().to_value(),
@ -6028,6 +6080,30 @@ pub const Module = struct {
const slice_value = slice_length; const slice_value = slice_length;
break :blk slice_value; break :blk slice_value;
}, },
.undefined => value_type.resolve(module).handle.get_poison(),
.string_literal => |string_literal| blk: {
const null_terminate = true;
const constant_string = module.llvm.context.get_constant_string(string_literal, null_terminate);
const u8_type = module.integer_type(8, false);
const global_variable = module.llvm.module.create_global_variable(.{
.linkage = .InternalLinkage,
.name = "conststring",
.initial_value = constant_string,
.type = u8_type.llvm.handle.?.get_array_type(string_literal.len + @intFromBool(null_terminate)).to_type(),
});
global_variable.set_unnamed_address(.global);
const slice_type = module.get_slice_type(.{
.type = u8_type,
});
assert(value_type == slice_type);
const slice_poison = slice_type.resolve(module).handle.get_poison();
const slice_pointer = module.llvm.builder.create_insert_value(slice_poison, global_variable.to_value(), 0);
const slice_length = module.llvm.builder.create_insert_value(slice_pointer, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(string_literal.len, 0).to_value(), 1);
const slice_value = slice_length;
break :blk slice_value;
},
else => @trap(), else => @trap(),
}; };
@ -6176,14 +6252,14 @@ pub const Module = struct {
if (expected_type) |lvt| assert(lvt == local.variable.type); if (expected_type) |lvt| assert(lvt == local.variable.type);
module.emit_local_storage(local, last_statement_debug_location); module.emit_local_storage(local, last_statement_debug_location);
module.emit_assignment(function, local.variable.storage.?, local.variable.initial_value); module.emit_assignment(function, local.variable.storage.?.llvm.?, local.variable.storage.?.type.?, local.variable.initial_value);
}, },
.assignment => |assignment| { .assignment => |assignment| {
module.analyze(function, assignment.left, .{}); module.analyze(function, assignment.left, .{});
switch (assignment.kind) { switch (assignment.kind) {
.@"=" => { .@"=" => {
module.analyze_value_type(function, assignment.right, .{ .type = assignment.left.type.?.bb.pointer.type }); module.analyze_value_type(function, assignment.right, .{ .type = assignment.left.type.?.bb.pointer.type });
module.emit_assignment(function, assignment.left, assignment.right); module.emit_assignment(function, assignment.left.llvm.?, assignment.left.type.?, assignment.right);
}, },
else => |kind| { else => |kind| {
const pointer_type = assignment.left.type.?.bb.pointer; const pointer_type = assignment.left.type.?.bb.pointer;
@ -6376,10 +6452,9 @@ pub const Module = struct {
} }
} }
fn emit_assignment(module: *Module, function: *Global, left: *Value, right: *Value) void { fn emit_assignment(module: *Module, function: *Global, left_llvm: *llvm.Value, left_type: *Type, right: *Value) void {
assert(left.llvm != null);
assert(right.llvm == null); assert(right.llvm == null);
const pointer_type = left.type.?; const pointer_type = left_type;
const value_type = right.type.?; const value_type = right.type.?;
assert(pointer_type.bb == .pointer); assert(pointer_type.bb == .pointer);
assert(pointer_type.bb.pointer.type == value_type); assert(pointer_type.bb.pointer.type == value_type);
@ -6389,7 +6464,7 @@ pub const Module = struct {
module.emit_value(function, right); module.emit_value(function, right);
_ = module.create_store(.{ _ = module.create_store(.{
.source_value = right.llvm.?, .source_value = right.llvm.?,
.destination_value = left.llvm.?, .destination_value = left_llvm,
.source_type = value_type, .source_type = value_type,
.destination_type = value_type, .destination_type = value_type,
.alignment = pointer_type.bb.pointer.alignment, .alignment = pointer_type.bb.pointer.alignment,
@ -6409,7 +6484,7 @@ pub const Module = struct {
const element_type = value_type.bb.array.element_type; const element_type = value_type.bb.array.element_type;
const alignment = element_type.get_byte_alignment(); const alignment = element_type.get_byte_alignment();
global_variable.to_value().set_alignment(alignment); global_variable.to_value().set_alignment(alignment);
_ = module.llvm.builder.create_memcpy(left.llvm.?, pointer_type.bb.pointer.alignment, global_variable.to_value(), alignment, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(array_initialization.values.len * pointer_type.bb.pointer.type.bb.array.element_type.get_byte_size(), @intFromBool(false)).to_value()); _ = module.llvm.builder.create_memcpy(left_llvm, pointer_type.bb.pointer.alignment, global_variable.to_value(), alignment, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(array_initialization.values.len * pointer_type.bb.pointer.type.bb.array.element_type.get_byte_size(), @intFromBool(false)).to_value());
}, },
false => @trap(), false => @trap(),
}, },
@ -6425,31 +6500,47 @@ pub const Module = struct {
global_variable.set_unnamed_address(.global); global_variable.set_unnamed_address(.global);
const alignment = value_type.get_byte_alignment(); const alignment = value_type.get_byte_alignment();
global_variable.to_value().set_alignment(alignment); global_variable.to_value().set_alignment(alignment);
_ = module.llvm.builder.create_memcpy(left.llvm.?, pointer_type.bb.pointer.alignment, global_variable.to_value(), alignment, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(value_type.get_byte_size(), @intFromBool(false)).to_value()); _ = module.llvm.builder.create_memcpy(left_llvm, pointer_type.bb.pointer.alignment, global_variable.to_value(), alignment, module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(value_type.get_byte_size(), @intFromBool(false)).to_value());
}, },
false => { false => {
var max_field_index: u64 = 0;
var field_mask: u64 = 0;
const fields = value_type.bb.structure.fields;
assert(fields.len <= 64);
for (aggregate_initialization.values, aggregate_initialization.names) |initialization_value, initialization_name| { for (aggregate_initialization.values, aggregate_initialization.names) |initialization_value, initialization_name| {
const field_index = for (value_type.bb.structure.fields, 0..) |*field, field_index| { const field_index = for (fields, 0..) |*field, field_index| {
if (lib.string.equal(field.name, initialization_name)) { if (lib.string.equal(field.name, initialization_name)) {
break field_index; break field_index;
} }
} else module.report_error(); } else module.report_error();
const field = &value_type.bb.structure.fields[field_index]; field_mask |= @as(@TypeOf(field_mask), 1) << @intCast(field_index);
const destination_pointer = module.llvm.builder.create_struct_gep(value_type.llvm.handle.?.to_struct(), left.llvm.?, @intCast(field_index)); max_field_index = @max(field_index, max_field_index);
// Create an auxiliary value const field = &fields[field_index];
const destination_value = module.values.add(); const destination_pointer = module.llvm.builder.create_struct_gep(value_type.llvm.handle.?.to_struct(), left_llvm, @intCast(field_index));
destination_value.* = .{ module.emit_assignment(function, destination_pointer, module.get_pointer_type(.{ .type = field.type }), initialization_value);
.bb = .local, // This does not matter
.llvm = destination_pointer,
.type = module.get_pointer_type(.{ .type = field.type }),
.kind = .left,
};
module.emit_assignment(function, destination_value, initialization_value);
} }
if (aggregate_initialization.zero) { if (aggregate_initialization.zero) {
const buffer_field_count: u64 = @bitSizeOf(@TypeOf(field_mask));
const raw_end_uninitialized_field_count = @clz(field_mask);
const unused_buffer_field_count = buffer_field_count - fields.len;
const end_uninitialized_field_count = raw_end_uninitialized_field_count - unused_buffer_field_count;
const initialized_field_count = @popCount(field_mask);
const uninitialized_field_count = fields.len - initialized_field_count;
if (uninitialized_field_count != end_uninitialized_field_count) {
@trap(); @trap();
} }
if (end_uninitialized_field_count == 0) {
module.report_error();
}
const field_index_offset = fields.len - end_uninitialized_field_count;
const destination_pointer = module.llvm.builder.create_struct_gep(value_type.llvm.handle.?.to_struct(), left_llvm, @intCast(field_index_offset));
const start_field = &fields[field_index_offset];
const memset_size = value_type.get_byte_size() - start_field.byte_offset;
_ = module.llvm.builder.create_memset(destination_pointer, module.integer_type(8, false).resolve(module).handle.get_zero().to_value(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(memset_size, 0).to_value(), pointer_type.bb.pointer.alignment);
}
}, },
}, },
.string_literal => |string_literal| { .string_literal => |string_literal| {
@ -6459,7 +6550,7 @@ pub const Module = struct {
const u8_type = module.integer_type(8, false); const u8_type = module.integer_type(8, false);
const global_variable = module.llvm.module.create_global_variable(.{ const global_variable = module.llvm.module.create_global_variable(.{
.linkage = .InternalLinkage, .linkage = .InternalLinkage,
.name = module.arena.join_string(&.{"conststring"}), .name = "conststring",
.initial_value = constant_string, .initial_value = constant_string,
.type = u8_type.llvm.handle.?.get_array_type(string_literal.len + @intFromBool(null_terminate)).to_type(), .type = u8_type.llvm.handle.?.get_array_type(string_literal.len + @intFromBool(null_terminate)).to_type(),
}); });
@ -6473,7 +6564,7 @@ pub const Module = struct {
.structure => |structure| switch (structure.is_slice) { .structure => |structure| switch (structure.is_slice) {
true => switch (slice_type == value_type) { true => switch (slice_type == value_type) {
true => { true => {
const pointer_to_pointer = module.llvm.builder.create_struct_gep(slice_type.llvm.handle.?.to_struct(), left.llvm.?, 0); const pointer_to_pointer = module.llvm.builder.create_struct_gep(slice_type.llvm.handle.?.to_struct(), left_llvm, 0);
const slice_pointer_type = slice_type.bb.structure.fields[0].type; const slice_pointer_type = slice_type.bb.structure.fields[0].type;
_ = module.create_store(.{ _ = module.create_store(.{
.destination_value = pointer_to_pointer, .destination_value = pointer_to_pointer,
@ -6481,7 +6572,7 @@ pub const Module = struct {
.source_type = slice_pointer_type, .source_type = slice_pointer_type,
.destination_type = slice_pointer_type, .destination_type = slice_pointer_type,
}); });
const pointer_to_length = module.llvm.builder.create_struct_gep(slice_type.llvm.handle.?.to_struct(), left.llvm.?, 1); const pointer_to_length = module.llvm.builder.create_struct_gep(slice_type.llvm.handle.?.to_struct(), left_llvm, 1);
const slice_length_type = slice_type.bb.structure.fields[1].type; const slice_length_type = slice_type.bb.structure.fields[1].type;
const slice_length_value = slice_length_type.llvm.handle.?.to_integer().get_constant(string_literal.len, @intFromBool(false)).to_value(); const slice_length_value = slice_length_type.llvm.handle.?.to_integer().get_constant(string_literal.len, @intFromBool(false)).to_value();
_ = module.create_store(.{ _ = module.create_store(.{
@ -6506,12 +6597,12 @@ pub const Module = struct {
const argument_types: []const *llvm.Type = &.{module.llvm.pointer_type}; const argument_types: []const *llvm.Type = &.{module.llvm.pointer_type};
const intrinsic_function = module.llvm.module.get_intrinsic_declaration(intrinsic_id, argument_types); const intrinsic_function = module.llvm.module.get_intrinsic_declaration(intrinsic_id, argument_types);
const intrinsic_function_type = module.llvm.context.get_intrinsic_type(intrinsic_id, argument_types); const intrinsic_function_type = module.llvm.context.get_intrinsic_type(intrinsic_id, argument_types);
const argument_values: []const *llvm.Value = &.{left.llvm.?}; const argument_values: []const *llvm.Value = &.{left_llvm};
_ = module.llvm.builder.create_call(intrinsic_function_type, intrinsic_function, argument_values); _ = module.llvm.builder.create_call(intrinsic_function_type, intrinsic_function, argument_values);
}, },
.va_arg => { .va_arg => {
const result = module.emit_va_arg(function, right, left); const result = module.emit_va_arg(function, right, left_llvm, left_type);
switch (result == left.llvm.?) { switch (result == left_llvm) {
true => {}, true => {},
false => switch (value_type.get_evaluation_kind()) { false => switch (value_type.get_evaluation_kind()) {
.scalar => { .scalar => {
@ -6525,8 +6616,8 @@ pub const Module = struct {
else => @trap(), else => @trap(),
}, },
.call => { .call => {
const result = module.emit_call(function, right, left); const result = module.emit_call(function, right, left_llvm, left_type);
assert(result == left.llvm); assert(result == left_llvm);
// if (result != left.llvm) { // if (result != left.llvm) {
// const call_ret_type_ev_kind = right.type.?.get_evaluation_kind(); // const call_ret_type_ev_kind = right.type.?.get_evaluation_kind();
// switch (call_ret_type_ev_kind) { // switch (call_ret_type_ev_kind) {
@ -6544,12 +6635,12 @@ pub const Module = struct {
const slice_pointer_type = value_type.bb.structure.fields[0].type; const slice_pointer_type = value_type.bb.structure.fields[0].type;
_ = module.create_store(.{ _ = module.create_store(.{
.source_value = slice_values[0], .source_value = slice_values[0],
.destination_value = left.llvm.?, .destination_value = left_llvm,
.source_type = slice_pointer_type, .source_type = slice_pointer_type,
.destination_type = slice_pointer_type, .destination_type = slice_pointer_type,
.alignment = pointer_type.bb.pointer.alignment, .alignment = pointer_type.bb.pointer.alignment,
}); });
const slice_length_destination = module.llvm.builder.create_struct_gep(value_type.llvm.handle.?.to_struct(), left.llvm.?, 1); const slice_length_destination = module.llvm.builder.create_struct_gep(value_type.llvm.handle.?.to_struct(), left_llvm, 1);
_ = module.create_store(.{ _ = module.create_store(.{
.source_value = slice_values[1], .source_value = slice_values[1],
.destination_value = slice_length_destination, .destination_value = slice_length_destination,
@ -6558,7 +6649,7 @@ pub const Module = struct {
}); });
}, },
.zero => { .zero => {
_ = module.llvm.builder.create_memset(left.llvm.?, module.integer_type(8, false).resolve(module).handle.get_zero().to_value(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(value_type.get_byte_size(), 0).to_value(), pointer_type.bb.pointer.alignment); _ = module.llvm.builder.create_memset(left_llvm, module.integer_type(8, false).resolve(module).handle.get_zero().to_value(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(value_type.get_byte_size(), 0).to_value(), pointer_type.bb.pointer.alignment);
}, },
else => @trap(), else => @trap(),
}, },

View File

@ -22,7 +22,7 @@ c_string_to_slice = fn (c_string: &u8) []u8
string_equal = fn(a: []u8, b: []u8) u1 string_equal = fn(a: []u8, b: []u8) u1
{ {
>result: #ReturnType() = 0; >result: #ReturnType = 0;
if (a.length == b.length) if (a.length == b.length)
{ {