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;
|
return byte_size;
|
||||||
}
|
}
|
||||||
pub fn get_bit_size(ty: *const Type) u64 {
|
pub fn get_bit_size(ty: *const Type) u64 {
|
||||||
_ = ty;
|
const bit_size: u64 = switch (ty.bb) {
|
||||||
@trap();
|
.integer => |integer| integer.bit_count,
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
return bit_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_byte_allocation_size(ty: *const Type) u64 {
|
pub fn get_byte_allocation_size(ty: *const Type) u64 {
|
||||||
@ -440,10 +443,47 @@ pub const Value = struct {
|
|||||||
binary: Binary,
|
binary: Binary,
|
||||||
variable_reference: *Variable,
|
variable_reference: *Variable,
|
||||||
local,
|
local,
|
||||||
|
intrinsic: Intrinsic,
|
||||||
},
|
},
|
||||||
type: ?*Type = null,
|
type: ?*Type = null,
|
||||||
llvm: ?*llvm.Value = 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 {
|
fn is_constant(value: *Value) bool {
|
||||||
return switch (value.bb) {
|
return switch (value.bb) {
|
||||||
.constant_integer => true,
|
.constant_integer => true,
|
||||||
@ -475,24 +515,6 @@ pub const Value = struct {
|
|||||||
zero,
|
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 {
|
const Builder = struct {
|
||||||
kind: Kind = .right,
|
kind: Kind = .right,
|
||||||
precedence: Precedence = .none,
|
precedence: Precedence = .none,
|
||||||
@ -1258,7 +1280,7 @@ pub const Module = struct {
|
|||||||
'#' => if (is_identifier_start_ch(module.content[module.offset + 1])) blk: {
|
'#' => if (is_identifier_start_ch(module.content[module.offset + 1])) blk: {
|
||||||
module.offset += 1;
|
module.offset += 1;
|
||||||
const value_intrinsic_identifier = module.parse_identifier();
|
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 .{
|
break :blk .{
|
||||||
.value_intrinsic = value_intrinsic,
|
.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 {
|
fn rule_before_value_intrinsic(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
_ = module;
|
const intrinsic = value_builder.token.value_intrinsic;
|
||||||
_ = value_builder;
|
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();
|
@trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2631,7 +2671,7 @@ pub const Module = struct {
|
|||||||
true => module.llvm.builder.create_integer_compare(.sle, left, right),
|
true => module.llvm.builder.create_integer_compare(.sle, left, right),
|
||||||
false => module.llvm.builder.create_integer_compare(.ule, left, right),
|
false => module.llvm.builder.create_integer_compare(.ule, left, right),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
break :blk result;
|
break :blk result;
|
||||||
@ -2645,6 +2685,21 @@ pub const Module = struct {
|
|||||||
.aggregate => @trap(),
|
.aggregate => @trap(),
|
||||||
.complex => @trap(),
|
.complex => @trap(),
|
||||||
} else @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(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2655,6 +2710,7 @@ pub const Module = struct {
|
|||||||
assert(value.type == null);
|
assert(value.type == null);
|
||||||
assert(value.llvm == 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) {
|
if (analysis.type) |expected_type| switch (expected_type.bb) {
|
||||||
.integer => |integer| switch (value.bb) {
|
.integer => |integer| switch (value.bb) {
|
||||||
.constant_integer => |constant_integer| switch (constant_integer.signed) {
|
.constant_integer => |constant_integer| switch (constant_integer.signed) {
|
||||||
@ -2708,11 +2764,27 @@ pub const Module = struct {
|
|||||||
module.report_error();
|
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(),
|
||||||
},
|
},
|
||||||
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) {
|
const value_type = if (analysis.type) |expected_type| expected_type else switch (value.bb) {
|
||||||
.binary => |binary| blk: {
|
.binary => |binary| blk: {
|
||||||
if (binary.left.bb == .constant_integer and binary.right.bb == .constant_integer) {
|
if (binary.left.bb == .constant_integer and binary.right.bb == .constant_integer) {
|
||||||
@ -3067,7 +3139,7 @@ const Token = union(Id) {
|
|||||||
integer: Integer,
|
integer: Integer,
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
value_keyword: Value.Keyword,
|
value_keyword: Value.Keyword,
|
||||||
value_intrinsic: Value.Intrinsic,
|
value_intrinsic: Value.Intrinsic.Id,
|
||||||
// Assignment operators
|
// Assignment operators
|
||||||
@"=",
|
@"=",
|
||||||
@"+=",
|
@"+=",
|
||||||
|
@ -186,6 +186,6 @@ const names = &[_][]const u8{
|
|||||||
"minimal_stack_arithmetic",
|
"minimal_stack_arithmetic",
|
||||||
"minimal_stack_arithmetic2",
|
"minimal_stack_arithmetic2",
|
||||||
"minimal_stack_arithmetic3",
|
"minimal_stack_arithmetic3",
|
||||||
|
"extend",
|
||||||
// "pointer",
|
// "pointer",
|
||||||
// "extend",
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user