Extend
All checks were successful
All checks were successful
This commit is contained in:
parent
1c50a06cce
commit
dd8bfda870
@ -329,8 +329,11 @@ pub const Type = struct {
|
||||
return byte_size;
|
||||
}
|
||||
pub fn get_bit_size(ty: *const Type) u64 {
|
||||
_ = ty;
|
||||
@trap();
|
||||
const bit_size: u64 = switch (ty.bb) {
|
||||
.integer => |integer| integer.bit_count,
|
||||
else => @trap(),
|
||||
};
|
||||
return bit_size;
|
||||
}
|
||||
|
||||
pub fn get_byte_allocation_size(ty: *const Type) u64 {
|
||||
@ -440,10 +443,47 @@ pub const Value = struct {
|
||||
binary: Binary,
|
||||
variable_reference: *Variable,
|
||||
local,
|
||||
intrinsic: Intrinsic,
|
||||
},
|
||||
type: ?*Type = null,
|
||||
llvm: ?*llvm.Value = null,
|
||||
|
||||
const Intrinsic = union(Id) {
|
||||
byte_size,
|
||||
cast,
|
||||
cast_to,
|
||||
extend: *Value,
|
||||
integer_max,
|
||||
int_from_enum,
|
||||
int_from_pointer,
|
||||
pointer_cast,
|
||||
select,
|
||||
trap,
|
||||
truncate,
|
||||
va_start,
|
||||
va_end,
|
||||
va_copy,
|
||||
va_arg,
|
||||
|
||||
const Id = enum {
|
||||
byte_size,
|
||||
cast,
|
||||
cast_to,
|
||||
extend,
|
||||
integer_max,
|
||||
int_from_enum,
|
||||
int_from_pointer,
|
||||
pointer_cast,
|
||||
select,
|
||||
trap,
|
||||
truncate,
|
||||
va_start,
|
||||
va_end,
|
||||
va_copy,
|
||||
va_arg,
|
||||
};
|
||||
};
|
||||
|
||||
fn is_constant(value: *Value) bool {
|
||||
return switch (value.bb) {
|
||||
.constant_integer => true,
|
||||
@ -475,24 +515,6 @@ pub const Value = struct {
|
||||
zero,
|
||||
};
|
||||
|
||||
const Intrinsic = enum {
|
||||
byte_size,
|
||||
cast,
|
||||
cast_to,
|
||||
extend,
|
||||
integer_max,
|
||||
int_from_enum,
|
||||
int_from_pointer,
|
||||
pointer_cast,
|
||||
select,
|
||||
trap,
|
||||
truncate,
|
||||
va_start,
|
||||
va_end,
|
||||
va_copy,
|
||||
va_arg,
|
||||
};
|
||||
|
||||
const Builder = struct {
|
||||
kind: Kind = .right,
|
||||
precedence: Precedence = .none,
|
||||
@ -1258,7 +1280,7 @@ pub const Module = struct {
|
||||
'#' => if (is_identifier_start_ch(module.content[module.offset + 1])) blk: {
|
||||
module.offset += 1;
|
||||
const value_intrinsic_identifier = module.parse_identifier();
|
||||
const value_intrinsic = lib.string.to_enum(Value.Intrinsic, value_intrinsic_identifier) orelse module.report_error();
|
||||
const value_intrinsic = lib.string.to_enum(Value.Intrinsic.Id, value_intrinsic_identifier) orelse module.report_error();
|
||||
break :blk .{
|
||||
.value_intrinsic = value_intrinsic,
|
||||
};
|
||||
@ -1642,8 +1664,26 @@ pub const Module = struct {
|
||||
}
|
||||
|
||||
fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||
_ = module;
|
||||
_ = value_builder;
|
||||
const intrinsic = value_builder.token.value_intrinsic;
|
||||
switch (intrinsic) {
|
||||
.extend => {
|
||||
module.skip_space();
|
||||
module.expect_character(left_parenthesis);
|
||||
module.skip_space();
|
||||
const arg_value = module.parse_value(.{});
|
||||
module.expect_character(right_parenthesis);
|
||||
const value = module.values.add();
|
||||
value.* = .{
|
||||
.bb = .{
|
||||
.intrinsic = .{
|
||||
.extend = arg_value,
|
||||
},
|
||||
},
|
||||
};
|
||||
return value;
|
||||
},
|
||||
else => @trap(),
|
||||
}
|
||||
@trap();
|
||||
}
|
||||
|
||||
@ -2631,7 +2671,7 @@ pub const Module = struct {
|
||||
true => module.llvm.builder.create_integer_compare(.sle, left, right),
|
||||
false => module.llvm.builder.create_integer_compare(.ule, left, right),
|
||||
},
|
||||
},
|
||||
},
|
||||
else => @trap(),
|
||||
};
|
||||
break :blk result;
|
||||
@ -2645,6 +2685,21 @@ pub const Module = struct {
|
||||
.aggregate => @trap(),
|
||||
.complex => @trap(),
|
||||
} else @trap(),
|
||||
.intrinsic => |intrinsic| switch (intrinsic) {
|
||||
.extend => |extended_value| blk: {
|
||||
if (extended_value.llvm == null) {
|
||||
module.emit_value(function, extended_value);
|
||||
}
|
||||
const llvm_value = extended_value.llvm orelse unreachable;
|
||||
const destination_type = value_type.llvm.handle.?;
|
||||
const extension_instruction = switch (extended_value.type.?.bb.integer.signed) {
|
||||
true => module.llvm.builder.create_sign_extend(llvm_value, destination_type),
|
||||
false => module.llvm.builder.create_zero_extend(llvm_value, destination_type),
|
||||
};
|
||||
break :blk extension_instruction;
|
||||
},
|
||||
else => @trap(),
|
||||
},
|
||||
else => @trap(),
|
||||
};
|
||||
|
||||
@ -2655,6 +2710,7 @@ pub const Module = struct {
|
||||
assert(value.type == null);
|
||||
assert(value.llvm == null);
|
||||
|
||||
// If a result type exists, then do the analysis against it
|
||||
if (analysis.type) |expected_type| switch (expected_type.bb) {
|
||||
.integer => |integer| switch (value.bb) {
|
||||
.constant_integer => |constant_integer| switch (constant_integer.signed) {
|
||||
@ -2708,11 +2764,27 @@ pub const Module = struct {
|
||||
module.report_error();
|
||||
}
|
||||
},
|
||||
.intrinsic => |intrinsic| switch (intrinsic) {
|
||||
.extend => |extended_value| {
|
||||
module.analyze_value_type(function, extended_value, .{});
|
||||
assert(extended_value.type != null);
|
||||
const destination_type = expected_type;
|
||||
const source_type = extended_value.type.?;
|
||||
|
||||
if (source_type.get_bit_size() > destination_type.get_bit_size()) {
|
||||
module.report_error();
|
||||
} else if (source_type.get_bit_size() == destination_type.get_bit_size() and source_type.is_signed() == destination_type.is_signed()) {
|
||||
module.report_error();
|
||||
}
|
||||
},
|
||||
else => @trap(),
|
||||
},
|
||||
else => @trap(),
|
||||
},
|
||||
else => @trap(),
|
||||
};
|
||||
|
||||
// Resolve the value type. If a result type does not exist, compute it
|
||||
const value_type = if (analysis.type) |expected_type| expected_type else switch (value.bb) {
|
||||
.binary => |binary| blk: {
|
||||
if (binary.left.bb == .constant_integer and binary.right.bb == .constant_integer) {
|
||||
@ -3067,7 +3139,7 @@ const Token = union(Id) {
|
||||
integer: Integer,
|
||||
identifier: []const u8,
|
||||
value_keyword: Value.Keyword,
|
||||
value_intrinsic: Value.Intrinsic,
|
||||
value_intrinsic: Value.Intrinsic.Id,
|
||||
// Assignment operators
|
||||
@"=",
|
||||
@"+=",
|
||||
|
@ -186,6 +186,6 @@ const names = &[_][]const u8{
|
||||
"minimal_stack_arithmetic",
|
||||
"minimal_stack_arithmetic2",
|
||||
"minimal_stack_arithmetic3",
|
||||
"extend",
|
||||
// "pointer",
|
||||
// "extend",
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user