Compare commits
1 Commits
208472ceaa
...
408d53a6f9
Author | SHA1 | Date | |
---|---|---|---|
408d53a6f9 |
@ -242,8 +242,7 @@ pub const Type = struct {
|
|||||||
|
|
||||||
const Kind = enum {
|
const Kind = enum {
|
||||||
abi,
|
abi,
|
||||||
storage,
|
memory,
|
||||||
loose,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const LLVM = struct {
|
const LLVM = struct {
|
||||||
@ -282,6 +281,13 @@ pub const Type = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_llvm(ty: *Type, kind: Kind) *llvm.Type {
|
||||||
|
return switch (kind) {
|
||||||
|
.abi => ty.llvm.abi.?,
|
||||||
|
.memory => ty.llvm.memory.?,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve(ty: *Type, module: *Module) void {
|
fn resolve(ty: *Type, module: *Module) void {
|
||||||
if (ty.llvm.abi == null) {
|
if (ty.llvm.abi == null) {
|
||||||
const abi_type = switch (ty.bb) {
|
const abi_type = switch (ty.bb) {
|
||||||
@ -3896,7 +3902,7 @@ pub const Module = struct {
|
|||||||
.intrinsic => |intrinsic| switch (intrinsic) {
|
.intrinsic => |intrinsic| switch (intrinsic) {
|
||||||
.va_arg => |va_arg| {
|
.va_arg => |va_arg| {
|
||||||
const raw_va_list_type = module.get_va_list_type();
|
const raw_va_list_type = module.get_va_list_type();
|
||||||
module.emit_value(function, va_arg.list);
|
module.emit_value(function, va_arg.list, .memory);
|
||||||
const uint64 = module.integer_type(64, false);
|
const uint64 = module.integer_type(64, false);
|
||||||
uint64.resolve(module);
|
uint64.resolve(module);
|
||||||
const va_list = module.llvm.builder.create_gep(.{
|
const va_list = module.llvm.builder.create_gep(.{
|
||||||
@ -4112,7 +4118,7 @@ pub const Module = struct {
|
|||||||
const coerce_to_type = argument_abi.get_coerce_to_type();
|
const coerce_to_type = argument_abi.get_coerce_to_type();
|
||||||
coerce_to_type.resolve(module);
|
coerce_to_type.resolve(module);
|
||||||
if (coerce_to_type.bb != .structure and semantic_argument_type.is_abi_equal(coerce_to_type, module) and argument_abi.attributes.direct.offset == 0) {
|
if (coerce_to_type.bb != .structure and semantic_argument_type.is_abi_equal(coerce_to_type, module) and argument_abi.attributes.direct.offset == 0) {
|
||||||
module.emit_value(function, semantic_argument_value);
|
module.emit_value(function, semantic_argument_value, .memory);
|
||||||
var v = switch (argument_abi.semantic_type.get_evaluation_kind()) {
|
var v = switch (argument_abi.semantic_type.get_evaluation_kind()) {
|
||||||
.aggregate => @trap(),
|
.aggregate => @trap(),
|
||||||
else => semantic_argument_value,
|
else => semantic_argument_value,
|
||||||
@ -4162,7 +4168,7 @@ pub const Module = struct {
|
|||||||
module.analyze_value_type(function, src, .{});
|
module.analyze_value_type(function, src, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.emit_value(function, semantic_argument_value);
|
module.emit_value(function, semantic_argument_value, .memory);
|
||||||
const destination_size = coerce_to_type.get_byte_size();
|
const destination_size = coerce_to_type.get_byte_size();
|
||||||
const source_size = argument_abi.semantic_type.get_byte_size();
|
const source_size = argument_abi.semantic_type.get_byte_size();
|
||||||
|
|
||||||
@ -4246,7 +4252,7 @@ pub const Module = struct {
|
|||||||
src.kind = .left;
|
src.kind = .left;
|
||||||
module.analyze_value_type(function, src, .{});
|
module.analyze_value_type(function, src, .{});
|
||||||
}
|
}
|
||||||
module.emit_value(function, src);
|
module.emit_value(function, src, .memory);
|
||||||
|
|
||||||
assert(src.type.?.bb == .pointer);
|
assert(src.type.?.bb == .pointer);
|
||||||
const source_type = src.type.?.bb.pointer.type;
|
const source_type = src.type.?.bb.pointer.type;
|
||||||
@ -4281,7 +4287,7 @@ pub const Module = struct {
|
|||||||
@trap();
|
@trap();
|
||||||
} else if (abi_argument_type.bb == .pointer and abi_argument_type.bb.pointer.type == semantic_argument_value.type) switch (semantic_argument_value.is_constant()) {
|
} else if (abi_argument_type.bb == .pointer and abi_argument_type.bb.pointer.type == semantic_argument_value.type) switch (semantic_argument_value.is_constant()) {
|
||||||
true => {
|
true => {
|
||||||
module.emit_value(function, semantic_argument_value);
|
module.emit_value(function, semantic_argument_value, .memory);
|
||||||
const global_variable = module.llvm.module.create_global_variable(.{
|
const global_variable = module.llvm.module.create_global_variable(.{
|
||||||
.linkage = .InternalLinkage,
|
.linkage = .InternalLinkage,
|
||||||
.name = "conststruct", // TODO: format properly
|
.name = "conststruct", // TODO: format properly
|
||||||
@ -4300,7 +4306,7 @@ pub const Module = struct {
|
|||||||
const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? });
|
const pointer_type = module.get_pointer_type(.{ .type = semantic_argument_value.type.? });
|
||||||
semantic_argument_value.type = null;
|
semantic_argument_value.type = null;
|
||||||
semantic_argument_value.kind = .left;
|
semantic_argument_value.kind = .left;
|
||||||
module.analyze(function, semantic_argument_value, .{ .type = pointer_type });
|
module.analyze(function, semantic_argument_value, .{ .type = pointer_type }, .memory);
|
||||||
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;
|
||||||
@ -4925,7 +4931,7 @@ 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 }, .memory);
|
||||||
|
|
||||||
if (global.variable.type == null) {
|
if (global.variable.type == null) {
|
||||||
global.variable.type = global.variable.initial_value.type;
|
global.variable.type = global.variable.initial_value.type;
|
||||||
@ -5077,9 +5083,9 @@ pub const Module = struct {
|
|||||||
type: ?*Type = null,
|
type: ?*Type = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn analyze(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis) void {
|
pub fn analyze(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis, type_kind: Type.Kind) void {
|
||||||
module.analyze_value_type(function, value, analysis);
|
module.analyze_value_type(function, value, analysis);
|
||||||
module.emit_value(function, value);
|
module.emit_value(function, value, type_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyze_value_type(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis) void {
|
pub fn analyze_value_type(module: *Module, function: ?*Global, value: *Value, analysis: ValueAnalysis) void {
|
||||||
@ -5969,15 +5975,15 @@ pub const Module = struct {
|
|||||||
const value_type = value.type.?;
|
const value_type = value.type.?;
|
||||||
switch (value.bb) {
|
switch (value.bb) {
|
||||||
.slice_expression => |slice_expression| {
|
.slice_expression => |slice_expression| {
|
||||||
module.emit_value(function, slice_expression.array_like);
|
module.emit_value(function, slice_expression.array_like, .memory);
|
||||||
switch (slice_expression.array_like.type.?.bb) {
|
switch (slice_expression.array_like.type.?.bb) {
|
||||||
.pointer => |pointer| switch (slice_expression.array_like.kind) {
|
.pointer => |pointer| switch (slice_expression.array_like.kind) {
|
||||||
.left => @trap(),
|
.left => @trap(),
|
||||||
.right => {
|
.right => {
|
||||||
const start = slice_expression.start;
|
const start = slice_expression.start;
|
||||||
module.emit_value(function, start);
|
module.emit_value(function, start, .memory);
|
||||||
const end = slice_expression.end orelse module.report_error();
|
const end = slice_expression.end orelse module.report_error();
|
||||||
module.emit_value(function, end);
|
module.emit_value(function, end, .memory);
|
||||||
const slice_pointer = module.llvm.builder.create_gep(.{
|
const slice_pointer = module.llvm.builder.create_gep(.{
|
||||||
.type = pointer.type.llvm.memory.?,
|
.type = pointer.type.llvm.memory.?,
|
||||||
.aggregate = slice_expression.array_like.llvm.?,
|
.aggregate = slice_expression.array_like.llvm.?,
|
||||||
@ -6002,7 +6008,7 @@ pub const Module = struct {
|
|||||||
// TODO: consider if we should emit an error here or it be a NOP
|
// TODO: consider if we should emit an error here or it be a NOP
|
||||||
module.report_error();
|
module.report_error();
|
||||||
} else {
|
} else {
|
||||||
module.emit_value(function, slice_expression.start);
|
module.emit_value(function, slice_expression.start, .memory);
|
||||||
const old_slice_pointer = module.llvm.builder.create_extract_value(slice_expression.array_like.llvm.?, 0);
|
const old_slice_pointer = module.llvm.builder.create_extract_value(slice_expression.array_like.llvm.?, 0);
|
||||||
const old_slice_length = module.llvm.builder.create_extract_value(slice_expression.array_like.llvm.?, 1);
|
const old_slice_length = module.llvm.builder.create_extract_value(slice_expression.array_like.llvm.?, 1);
|
||||||
const slice_pointer = module.llvm.builder.create_gep(.{
|
const slice_pointer = module.llvm.builder.create_gep(.{
|
||||||
@ -6023,34 +6029,34 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_value(module: *Module, function: ?*Global, value: *Value) void {
|
pub fn emit_value(module: *Module, function: ?*Global, value: *Value, type_kind: Type.Kind) void {
|
||||||
const value_type = value.type orelse unreachable;
|
const value_type = value.type orelse unreachable;
|
||||||
assert(value.llvm == null);
|
assert(value.llvm == null);
|
||||||
value_type.resolve(module);
|
value_type.resolve(module);
|
||||||
|
|
||||||
const llvm_value: *llvm.Value = switch (value.bb) {
|
const llvm_value: *llvm.Value = switch (value.bb) {
|
||||||
.constant_integer => |constant_integer| value_type.llvm.abi.?.to_integer().get_constant(constant_integer.value, @intFromBool(constant_integer.signed)).to_value(),
|
.constant_integer => |constant_integer| value_type.get_llvm(type_kind).to_integer().get_constant(constant_integer.value, @intFromBool(constant_integer.signed)).to_value(),
|
||||||
.unary => |unary| switch (unary.id) {
|
.unary => |unary| switch (unary.id) {
|
||||||
.@"-" => blk: {
|
.@"-" => blk: {
|
||||||
const unary_value = unary.value.llvm orelse b: {
|
const unary_value = unary.value.llvm orelse b: {
|
||||||
module.emit_value(function, unary.value);
|
module.emit_value(function, unary.value, type_kind);
|
||||||
break :b unary.value.llvm orelse unreachable;
|
break :b unary.value.llvm orelse unreachable;
|
||||||
};
|
};
|
||||||
break :blk module.negate_llvm_value(unary_value, unary.value.is_constant());
|
break :blk module.negate_llvm_value(unary_value, unary.value.is_constant());
|
||||||
},
|
},
|
||||||
.@"&" => blk: {
|
.@"&" => blk: {
|
||||||
assert(value_type == unary.value.type);
|
assert(value_type == unary.value.type);
|
||||||
module.emit_value(function, unary.value);
|
module.emit_value(function, unary.value, type_kind);
|
||||||
break :blk unary.value.llvm orelse unreachable;
|
break :blk unary.value.llvm orelse unreachable;
|
||||||
},
|
},
|
||||||
.@"!" => switch (unary.value.type == value_type) {
|
.@"!" => switch (unary.value.type == value_type) {
|
||||||
true => b: {
|
true => b: {
|
||||||
module.emit_value(function, unary.value);
|
module.emit_value(function, unary.value, type_kind);
|
||||||
break :b module.llvm.builder.create_not(unary.value.llvm.?);
|
break :b module.llvm.builder.create_not(unary.value.llvm.?);
|
||||||
},
|
},
|
||||||
false => switch (unary.value.type.?.bb) {
|
false => switch (unary.value.type.?.bb) {
|
||||||
.pointer => b: {
|
.pointer => b: {
|
||||||
module.emit_value(function, unary.value);
|
module.emit_value(function, unary.value, type_kind);
|
||||||
break :b module.llvm.builder.create_integer_compare(.eq, unary.value.llvm.?, unary.value.type.?.llvm.abi.?.get_zero().to_value());
|
break :b module.llvm.builder.create_integer_compare(.eq, unary.value.llvm.?, unary.value.type.?.llvm.abi.?.get_zero().to_value());
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
@ -6060,11 +6066,11 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.binary => |binary| blk: {
|
.binary => |binary| blk: {
|
||||||
const left = if (binary.left.llvm) |left_llvm| left_llvm else b: {
|
const left = if (binary.left.llvm) |left_llvm| left_llvm else b: {
|
||||||
module.emit_value(function, binary.left);
|
module.emit_value(function, binary.left, .abi);
|
||||||
break :b binary.left.llvm orelse unreachable;
|
break :b binary.left.llvm orelse unreachable;
|
||||||
};
|
};
|
||||||
const right = if (binary.right.llvm) |right_llvm| right_llvm else b: {
|
const right = if (binary.right.llvm) |right_llvm| right_llvm else b: {
|
||||||
module.emit_value(function, binary.right);
|
module.emit_value(function, binary.right, .abi);
|
||||||
break :b binary.right.llvm orelse unreachable;
|
break :b binary.right.llvm orelse unreachable;
|
||||||
};
|
};
|
||||||
const result = switch (value_type.bb) {
|
const result = switch (value_type.bb) {
|
||||||
@ -6176,7 +6182,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.extend => |extended_value| blk: {
|
.extend => |extended_value| blk: {
|
||||||
if (extended_value.llvm == null) {
|
if (extended_value.llvm == null) {
|
||||||
module.emit_value(function, extended_value);
|
module.emit_value(function, extended_value, type_kind);
|
||||||
}
|
}
|
||||||
const llvm_value = extended_value.llvm orelse unreachable;
|
const llvm_value = extended_value.llvm orelse unreachable;
|
||||||
const destination_type = value_type.llvm.abi.?;
|
const destination_type = value_type.llvm.abi.?;
|
||||||
@ -6194,20 +6200,20 @@ pub const Module = struct {
|
|||||||
break :blk constant_integer.to_value();
|
break :blk constant_integer.to_value();
|
||||||
},
|
},
|
||||||
.int_from_enum => |enum_value| blk: {
|
.int_from_enum => |enum_value| blk: {
|
||||||
module.emit_value(function, enum_value);
|
module.emit_value(function, enum_value, type_kind);
|
||||||
break :blk enum_value.llvm.?;
|
break :blk enum_value.llvm.?;
|
||||||
},
|
},
|
||||||
.int_from_pointer => |pointer_value| blk: {
|
.int_from_pointer => |pointer_value| blk: {
|
||||||
module.emit_value(function, pointer_value);
|
module.emit_value(function, pointer_value, type_kind);
|
||||||
const int = module.llvm.builder.create_ptr_to_int(pointer_value.llvm.?, value_type.llvm.abi.?);
|
const int = module.llvm.builder.create_ptr_to_int(pointer_value.llvm.?, value_type.llvm.abi.?);
|
||||||
break :blk int;
|
break :blk int;
|
||||||
},
|
},
|
||||||
.pointer_cast => |pointer_value| blk: {
|
.pointer_cast => |pointer_value| blk: {
|
||||||
module.emit_value(function, pointer_value);
|
module.emit_value(function, pointer_value, type_kind);
|
||||||
break :blk pointer_value.llvm.?;
|
break :blk pointer_value.llvm.?;
|
||||||
},
|
},
|
||||||
.select => |select| blk: {
|
.select => |select| blk: {
|
||||||
module.emit_value(function, select.condition);
|
module.emit_value(function, select.condition, type_kind);
|
||||||
const condition = switch (select.condition.type.?.bb) {
|
const condition = switch (select.condition.type.?.bb) {
|
||||||
.integer => |integer| switch (integer.bit_count) {
|
.integer => |integer| switch (integer.bit_count) {
|
||||||
1 => select.condition.llvm.?,
|
1 => select.condition.llvm.?,
|
||||||
@ -6215,13 +6221,13 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
module.emit_value(function, select.true_value);
|
module.emit_value(function, select.true_value, type_kind);
|
||||||
module.emit_value(function, select.false_value);
|
module.emit_value(function, select.false_value, type_kind);
|
||||||
const result = module.llvm.builder.create_select(condition, select.true_value.llvm.?, select.false_value.llvm.?);
|
const result = module.llvm.builder.create_select(condition, select.true_value.llvm.?, select.false_value.llvm.?);
|
||||||
break :blk result;
|
break :blk result;
|
||||||
},
|
},
|
||||||
.string_to_enum => |string_to_enum| blk: {
|
.string_to_enum => |string_to_enum| blk: {
|
||||||
module.emit_value(function, string_to_enum.string_value);
|
module.emit_value(function, string_to_enum.string_value, type_kind);
|
||||||
const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable;
|
const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable;
|
||||||
const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0);
|
const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0);
|
||||||
const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1);
|
const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1);
|
||||||
@ -6244,7 +6250,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.truncate => |value_to_truncate| blk: {
|
.truncate => |value_to_truncate| blk: {
|
||||||
if (value_to_truncate.llvm == null) {
|
if (value_to_truncate.llvm == null) {
|
||||||
module.emit_value(function, value_to_truncate);
|
module.emit_value(function, value_to_truncate, type_kind);
|
||||||
}
|
}
|
||||||
const llvm_value = value_to_truncate.llvm orelse unreachable;
|
const llvm_value = value_to_truncate.llvm orelse unreachable;
|
||||||
const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.abi.?);
|
const truncate = module.llvm.builder.create_truncate(llvm_value, value_type.llvm.abi.?);
|
||||||
@ -6252,7 +6258,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.va_arg => module.emit_va_arg(function.?, value, null, 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, .memory);
|
||||||
|
|
||||||
const intrinsic_id = module.llvm.intrinsic_table.va_end;
|
const intrinsic_id = module.llvm.intrinsic_table.va_end;
|
||||||
const argument_types: []const *llvm.Type = &.{module.llvm.pointer_type};
|
const argument_types: []const *llvm.Type = &.{module.llvm.pointer_type};
|
||||||
@ -6265,7 +6271,7 @@ pub const Module = struct {
|
|||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
.dereference => |dereferenceable_value| blk: {
|
.dereference => |dereferenceable_value| blk: {
|
||||||
module.emit_value(function, dereferenceable_value);
|
module.emit_value(function, dereferenceable_value, .memory);
|
||||||
const result = switch (value.kind) {
|
const result = switch (value.kind) {
|
||||||
.left => @trap(),
|
.left => @trap(),
|
||||||
.right => module.create_load(.{
|
.right => module.create_load(.{
|
||||||
@ -6283,7 +6289,7 @@ pub const Module = struct {
|
|||||||
const element_count = array_initialization.values.len;
|
const element_count = array_initialization.values.len;
|
||||||
const llvm_values = llvm_value_buffer[0..element_count];
|
const llvm_values = llvm_value_buffer[0..element_count];
|
||||||
for (array_initialization.values, llvm_values) |v, *llvm_value| {
|
for (array_initialization.values, llvm_values) |v, *llvm_value| {
|
||||||
module.emit_value(function, v);
|
module.emit_value(function, v, .memory);
|
||||||
llvm_value.* = v.llvm.?.to_constant();
|
llvm_value.* = v.llvm.?.to_constant();
|
||||||
}
|
}
|
||||||
value_type.bb.array.element_type.resolve(module);
|
value_type.bb.array.element_type.resolve(module);
|
||||||
@ -6296,8 +6302,8 @@ pub const Module = struct {
|
|||||||
.left => switch (array_expression.array_like.type.?.bb) {
|
.left => switch (array_expression.array_like.type.?.bb) {
|
||||||
.pointer => |pointer| switch (pointer.type.bb) {
|
.pointer => |pointer| switch (pointer.type.bb) {
|
||||||
.array => |array| blk: {
|
.array => |array| blk: {
|
||||||
module.emit_value(function, array_expression.array_like);
|
module.emit_value(function, array_expression.array_like, .memory);
|
||||||
module.emit_value(function, array_expression.index);
|
module.emit_value(function, array_expression.index, .memory);
|
||||||
const uint64 = module.integer_type(64, false);
|
const uint64 = module.integer_type(64, false);
|
||||||
uint64.resolve(module);
|
uint64.resolve(module);
|
||||||
const zero_index = uint64.llvm.abi.?.to_integer().get_constant(0, @intFromBool(false)).to_value();
|
const zero_index = uint64.llvm.abi.?.to_integer().get_constant(0, @intFromBool(false)).to_value();
|
||||||
@ -6316,8 +6322,8 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.structure => |structure| blk: {
|
.structure => |structure| blk: {
|
||||||
assert(structure.is_slice);
|
assert(structure.is_slice);
|
||||||
module.emit_value(function, array_expression.array_like);
|
module.emit_value(function, array_expression.array_like, .memory);
|
||||||
module.emit_value(function, array_expression.index);
|
module.emit_value(function, array_expression.index, .memory);
|
||||||
const pointer_type = structure.fields[0].type;
|
const pointer_type = structure.fields[0].type;
|
||||||
const element_type = pointer_type.bb.pointer.type;
|
const element_type = pointer_type.bb.pointer.type;
|
||||||
const pointer_load = module.create_load(.{ .type = structure.fields[0].type, .value = array_expression.array_like.llvm.? });
|
const pointer_load = module.create_load(.{ .type = structure.fields[0].type, .value = array_expression.array_like.llvm.? });
|
||||||
@ -6336,8 +6342,8 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
.pointer => |real_pointer| blk: {
|
.pointer => |real_pointer| blk: {
|
||||||
module.emit_value(function, array_expression.array_like);
|
module.emit_value(function, array_expression.array_like, .memory);
|
||||||
module.emit_value(function, array_expression.index);
|
module.emit_value(function, array_expression.index, .memory);
|
||||||
// TODO: consider not emitting the and doing straight GEP?
|
// TODO: consider not emitting the and doing straight GEP?
|
||||||
const pointer_load = module.create_load(.{ .type = pointer.type, .value = array_expression.array_like.llvm.? });
|
const pointer_load = module.create_load(.{ .type = pointer.type, .value = array_expression.array_like.llvm.? });
|
||||||
const element_type = real_pointer.type;
|
const element_type = real_pointer.type;
|
||||||
@ -6360,8 +6366,8 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.right => switch (array_expression.array_like.type.?.bb) {
|
.right => switch (array_expression.array_like.type.?.bb) {
|
||||||
.pointer => |pointer| blk: {
|
.pointer => |pointer| blk: {
|
||||||
module.emit_value(function, array_expression.array_like);
|
module.emit_value(function, array_expression.array_like, .memory);
|
||||||
module.emit_value(function, array_expression.index);
|
module.emit_value(function, array_expression.index, .memory);
|
||||||
const gep = module.llvm.builder.create_gep(.{
|
const gep = module.llvm.builder.create_gep(.{
|
||||||
.type = pointer.type.llvm.memory.?,
|
.type = pointer.type.llvm.memory.?,
|
||||||
.aggregate = array_expression.array_like.llvm.?,
|
.aggregate = array_expression.array_like.llvm.?,
|
||||||
@ -6376,8 +6382,8 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.structure => |structure| switch (structure.is_slice) {
|
.structure => |structure| switch (structure.is_slice) {
|
||||||
true => blk: {
|
true => blk: {
|
||||||
module.emit_value(function, array_expression.array_like);
|
module.emit_value(function, array_expression.array_like, .memory);
|
||||||
module.emit_value(function, array_expression.index);
|
module.emit_value(function, array_expression.index, .memory);
|
||||||
const pointer_extract = module.llvm.builder.create_extract_value(array_expression.array_like.llvm.?, 0);
|
const pointer_extract = module.llvm.builder.create_extract_value(array_expression.array_like.llvm.?, 0);
|
||||||
const element_type = structure.fields[0].type.bb.pointer.type;
|
const element_type = structure.fields[0].type.bb.pointer.type;
|
||||||
const gep = module.llvm.builder.create_gep(.{
|
const gep = module.llvm.builder.create_gep(.{
|
||||||
@ -6403,11 +6409,11 @@ pub const Module = struct {
|
|||||||
break field.value;
|
break field.value;
|
||||||
}
|
}
|
||||||
} else module.report_error();
|
} else module.report_error();
|
||||||
const llvm_value = value_type.llvm.abi.?.to_integer().get_constant(enum_int_value, @intFromBool(false));
|
const llvm_value = value_type.get_llvm(type_kind).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: {
|
||||||
module.emit_value(function, field_access.aggregate);
|
module.emit_value(function, field_access.aggregate, .memory);
|
||||||
const field_name = field_access.field;
|
const field_name = field_access.field;
|
||||||
switch (field_access.aggregate.kind) {
|
switch (field_access.aggregate.kind) {
|
||||||
.left => switch (field_access.aggregate.type.?.bb) {
|
.left => switch (field_access.aggregate.type.?.bb) {
|
||||||
@ -6487,7 +6493,7 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
} else unreachable;
|
} else unreachable;
|
||||||
const field = &bits.fields[declaration_index];
|
const field = &bits.fields[declaration_index];
|
||||||
module.emit_value(function, field_value);
|
module.emit_value(function, field_value, .memory);
|
||||||
const extended = module.llvm.builder.create_zero_extend(field_value.llvm.?, llvm_type);
|
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 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);
|
const or_value = module.llvm.builder.create_or(result, shl);
|
||||||
@ -6500,8 +6506,9 @@ pub const Module = struct {
|
|||||||
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];
|
||||||
|
|
||||||
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, .memory);
|
||||||
constant.* = field_value.llvm.?.to_constant();
|
constant.* = field_value.llvm.?.to_constant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6512,7 +6519,7 @@ pub const Module = struct {
|
|||||||
|
|
||||||
for (constants[aggregate_initialization.values.len..], structure.fields[aggregate_initialization.values.len..]) |*constant, *field| {
|
for (constants[aggregate_initialization.values.len..], structure.fields[aggregate_initialization.values.len..]) |*constant, *field| {
|
||||||
field.type.resolve(module);
|
field.type.resolve(module);
|
||||||
constant.* = field.type.llvm.abi.?.get_zero();
|
constant.* = field.type.llvm.memory.?.get_zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const constant_struct = value_type.llvm.abi.?.to_struct().get_constant(constants);
|
const constant_struct = value_type.llvm.abi.?.to_struct().get_constant(constants);
|
||||||
@ -6614,7 +6621,7 @@ pub const Module = struct {
|
|||||||
const return_value = rv orelse module.report_error();
|
const return_value = rv orelse module.report_error();
|
||||||
module.analyze(function, return_value, .{
|
module.analyze(function, return_value, .{
|
||||||
.type = return_abi.semantic_type,
|
.type = return_abi.semantic_type,
|
||||||
});
|
}, .memory);
|
||||||
|
|
||||||
if (module.has_debug_info) {
|
if (module.has_debug_info) {
|
||||||
module.llvm.builder.set_current_debug_location(last_statement_debug_location);
|
module.llvm.builder.set_current_debug_location(last_statement_debug_location);
|
||||||
@ -6717,7 +6724,7 @@ pub const Module = struct {
|
|||||||
module.emit_assignment(function, local.variable.storage.?.llvm.?, local.variable.storage.?.type.?, 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, .{}, .memory);
|
||||||
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 });
|
||||||
@ -6728,7 +6735,7 @@ pub const Module = struct {
|
|||||||
const element_type = pointer_type.type;
|
const element_type = pointer_type.type;
|
||||||
assert(element_type.get_evaluation_kind() == .scalar);
|
assert(element_type.get_evaluation_kind() == .scalar);
|
||||||
const load = module.create_load(.{ .type = element_type, .value = assignment.left.llvm.?, .alignment = pointer_type.alignment });
|
const load = module.create_load(.{ .type = element_type, .value = assignment.left.llvm.?, .alignment = pointer_type.alignment });
|
||||||
module.analyze(function, assignment.right, .{ .type = element_type });
|
module.analyze(function, assignment.right, .{ .type = element_type }, .memory);
|
||||||
const a = load;
|
const a = load;
|
||||||
const b = assignment.right.llvm.?;
|
const b = assignment.right.llvm.?;
|
||||||
const right = switch (kind) {
|
const right = switch (kind) {
|
||||||
@ -6804,14 +6811,14 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.expression => |expression_value| {
|
.expression => |expression_value| {
|
||||||
module.analyze(function, expression_value, .{});
|
module.analyze(function, expression_value, .{}, .memory);
|
||||||
},
|
},
|
||||||
.@"if" => |if_statement| {
|
.@"if" => |if_statement| {
|
||||||
const taken_block = module.llvm.context.create_basic_block("if.true", llvm_function);
|
const taken_block = module.llvm.context.create_basic_block("if.true", llvm_function);
|
||||||
const not_taken_block = module.llvm.context.create_basic_block("if.false", llvm_function);
|
const not_taken_block = module.llvm.context.create_basic_block("if.false", llvm_function);
|
||||||
const exit_block = module.llvm.context.create_basic_block("if.end", null);
|
const exit_block = module.llvm.context.create_basic_block("if.end", null);
|
||||||
|
|
||||||
module.analyze(function, if_statement.condition, .{});
|
module.analyze(function, if_statement.condition, .{}, .memory);
|
||||||
const llvm_condition = switch (if_statement.condition.type.?.bb) {
|
const llvm_condition = switch (if_statement.condition.type.?.bb) {
|
||||||
.integer => |integer| if (integer.bit_count != 1) module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()) else if_statement.condition.llvm.?,
|
.integer => |integer| if (integer.bit_count != 1) module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()) else if_statement.condition.llvm.?,
|
||||||
.pointer => module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()),
|
.pointer => module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.abi.?.get_zero().to_value()),
|
||||||
@ -6875,7 +6882,7 @@ pub const Module = struct {
|
|||||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||||
module.llvm.builder.position_at_end(loop_entry_block);
|
module.llvm.builder.position_at_end(loop_entry_block);
|
||||||
|
|
||||||
module.analyze(function, while_loop.condition, .{});
|
module.analyze(function, while_loop.condition, .{}, .abi);
|
||||||
|
|
||||||
const boolean_type = module.integer_type(1, false);
|
const boolean_type = module.integer_type(1, false);
|
||||||
const condition_value = switch (while_loop.condition.type == boolean_type) {
|
const condition_value = switch (while_loop.condition.type == boolean_type) {
|
||||||
@ -6914,7 +6921,7 @@ pub const Module = struct {
|
|||||||
const exit_block = module.llvm.context.create_basic_block("exit_block", llvm_function);
|
const exit_block = module.llvm.context.create_basic_block("exit_block", llvm_function);
|
||||||
current_function.exit_block = exit_block;
|
current_function.exit_block = exit_block;
|
||||||
|
|
||||||
module.analyze(function, switch_statement.discriminant, .{});
|
module.analyze(function, switch_statement.discriminant, .{}, .abi);
|
||||||
const switch_discriminant_type = switch_statement.discriminant.type.?;
|
const switch_discriminant_type = switch_statement.discriminant.type.?;
|
||||||
|
|
||||||
switch (switch_discriminant_type.bb) {
|
switch (switch_discriminant_type.bb) {
|
||||||
@ -6932,7 +6939,7 @@ pub const Module = struct {
|
|||||||
else_clause_index = clause_index;
|
else_clause_index = clause_index;
|
||||||
} else {
|
} else {
|
||||||
for (clause.values) |v| {
|
for (clause.values) |v| {
|
||||||
module.analyze(function, v, .{ .type = switch_discriminant_type });
|
module.analyze(function, v, .{ .type = switch_discriminant_type }, .abi);
|
||||||
if (!v.is_constant()) {
|
if (!v.is_constant()) {
|
||||||
module.report_error();
|
module.report_error();
|
||||||
}
|
}
|
||||||
@ -6990,7 +6997,7 @@ pub const Module = struct {
|
|||||||
|
|
||||||
switch (value_type.get_evaluation_kind()) {
|
switch (value_type.get_evaluation_kind()) {
|
||||||
.scalar => {
|
.scalar => {
|
||||||
module.emit_value(function, right);
|
module.emit_value(function, right, .memory);
|
||||||
_ = module.create_store(.{
|
_ = module.create_store(.{
|
||||||
.source_value = right.llvm.?,
|
.source_value = right.llvm.?,
|
||||||
.destination_value = left_llvm,
|
.destination_value = left_llvm,
|
||||||
@ -7001,7 +7008,7 @@ pub const Module = struct {
|
|||||||
.aggregate => switch (right.bb) {
|
.aggregate => switch (right.bb) {
|
||||||
.array_initialization => |array_initialization| switch (array_initialization.is_constant) {
|
.array_initialization => |array_initialization| switch (array_initialization.is_constant) {
|
||||||
true => {
|
true => {
|
||||||
module.emit_value(function, right);
|
module.emit_value(function, right, .memory);
|
||||||
const global_variable = module.llvm.module.create_global_variable(.{
|
const global_variable = module.llvm.module.create_global_variable(.{
|
||||||
.linkage = .InternalLinkage,
|
.linkage = .InternalLinkage,
|
||||||
.name = "constarray", // TODO: format properly
|
.name = "constarray", // TODO: format properly
|
||||||
@ -7020,7 +7027,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.aggregate_initialization => |aggregate_initialization| switch (aggregate_initialization.is_constant) {
|
.aggregate_initialization => |aggregate_initialization| switch (aggregate_initialization.is_constant) {
|
||||||
true => {
|
true => {
|
||||||
module.emit_value(function, right);
|
module.emit_value(function, right, .memory);
|
||||||
const global_variable = module.llvm.module.create_global_variable(.{
|
const global_variable = module.llvm.module.create_global_variable(.{
|
||||||
.linkage = .InternalLinkage,
|
.linkage = .InternalLinkage,
|
||||||
.name = "conststruct", // TODO: format properly
|
.name = "conststruct", // TODO: format properly
|
||||||
@ -7126,7 +7133,7 @@ pub const Module = struct {
|
|||||||
},
|
},
|
||||||
.intrinsic => |intrinsic| switch (intrinsic) {
|
.intrinsic => |intrinsic| switch (intrinsic) {
|
||||||
.string_to_enum => |string_to_enum| {
|
.string_to_enum => |string_to_enum| {
|
||||||
module.emit_value(function, string_to_enum.string_value);
|
module.emit_value(function, string_to_enum.string_value, .memory);
|
||||||
const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable;
|
const s2e = string_to_enum.enum_type.bb.enumerator.string_to_enum orelse unreachable;
|
||||||
const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0);
|
const first_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 0);
|
||||||
const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1);
|
const second_field = module.llvm.builder.create_extract_value(string_to_enum.string_value.llvm.?, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user