Implement pointer_cast
This commit is contained in:
parent
570d507839
commit
37d45aa101
@ -944,6 +944,10 @@ pub const Builder = opaque {
|
|||||||
return api.LLVMBuildPtrToInt(builder, value, destination_type, "");
|
return api.LLVMBuildPtrToInt(builder, value, destination_type, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_pointer_cast(builder: *Builder, value: *Value, destination_type: *Type) *Value {
|
||||||
|
return api.LLVMBuildPointerCast(builder, value, destination_type, "");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_truncate(builder: *Builder, value: *Value, destination_type: *Type) *Value {
|
pub fn create_truncate(builder: *Builder, value: *Value, destination_type: *Type) *Value {
|
||||||
return api.LLVMBuildTrunc(builder, value, destination_type, "");
|
return api.LLVMBuildTrunc(builder, value, destination_type, "");
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ OS_Linux_MAP = bits u32
|
|||||||
}
|
}
|
||||||
|
|
||||||
[extern] mmap = fn [cc(c)] (address: u64, size: u64, protection: OS_Linux_PROT, map: OS_Linux_MAP, file_descriptor: s32, offset: s64) &u8;
|
[extern] mmap = fn [cc(c)] (address: u64, size: u64, protection: OS_Linux_PROT, map: OS_Linux_MAP, file_descriptor: s32, offset: s64) &u8;
|
||||||
|
[extern] mprotect = fn [cc(c)] (address: u64, size: u64, protection: OS_Linux_PROT) s32;
|
||||||
|
|
||||||
OS_ProtectionFlags = bits
|
OS_ProtectionFlags = bits
|
||||||
{
|
{
|
||||||
@ -89,6 +90,16 @@ os_reserve = fn (base: u64, size: u64, protection: OS_ProtectionFlags, map: OS_M
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_commit = fn (address: u64, size: u64, protection: OS_ProtectionFlags) void
|
||||||
|
{
|
||||||
|
>protection_flags = os_linux_protection_flags(protection);
|
||||||
|
>result = mprotect(address, size, protection_flags);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Arena = struct
|
Arena = struct
|
||||||
{
|
{
|
||||||
reserved_size: u64,
|
reserved_size: u64,
|
||||||
@ -109,6 +120,35 @@ ArenaInitialization = struct
|
|||||||
|
|
||||||
arena_initialize = fn (initialization: ArenaInitialization) &Arena
|
arena_initialize = fn (initialization: ArenaInitialization) &Arena
|
||||||
{
|
{
|
||||||
|
>protection_flags: OS_ProtectionFlags = {
|
||||||
|
.read = 1,
|
||||||
|
.write = 1,
|
||||||
|
zero,
|
||||||
|
};
|
||||||
|
|
||||||
|
>map_flags: OS_MapFlags = {
|
||||||
|
.private = 1,
|
||||||
|
.anonymous = 1,
|
||||||
|
.no_reserve = 1,
|
||||||
|
.populate = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
>arena: &Arena = #pointer_cast(os_reserve(0, initialization.reserved_size, protection_flags, map_flags));
|
||||||
|
os_commit(#int_from_pointer(arena), initialization.initial_size, {
|
||||||
|
.read = 1,
|
||||||
|
.write = 1,
|
||||||
|
zero,
|
||||||
|
});
|
||||||
|
|
||||||
|
//arena.& = {
|
||||||
|
// .reserved_size = initialization.reserved_size,
|
||||||
|
// .os_position = initialization.initial_size,
|
||||||
|
// .position = minimum_position,
|
||||||
|
// .granularity = initialization.granularity,
|
||||||
|
// zero,
|
||||||
|
//};
|
||||||
|
|
||||||
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
[export] main = fn [cc(c)] () s32
|
||||||
|
@ -1114,6 +1114,7 @@ pub const Value = struct {
|
|||||||
return switch (value.bb) {
|
return switch (value.bb) {
|
||||||
.constant_integer, .constant_array => true,
|
.constant_integer, .constant_array => true,
|
||||||
.struct_initialization => |si| si.is_constant,
|
.struct_initialization => |si| si.is_constant,
|
||||||
|
.instruction => false,
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2203,8 +2204,6 @@ const Converter = struct {
|
|||||||
.@"return" => {
|
.@"return" => {
|
||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
|
|
||||||
const abi_return_type = current_function_type.abi_return_type;
|
|
||||||
_ = abi_return_type;
|
|
||||||
const return_type_abi = ¤t_function_type.return_type_abi;
|
const return_type_abi = ¤t_function_type.return_type_abi;
|
||||||
const returns_nothing = converter.consume_character_if_match(';');
|
const returns_nothing = converter.consume_character_if_match(';');
|
||||||
if (returns_nothing) {
|
if (returns_nothing) {
|
||||||
@ -2225,12 +2224,13 @@ const Converter = struct {
|
|||||||
@trap();
|
@trap();
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
assert(return_value.type.is_abi_equal(return_type_abi.semantic_type));
|
||||||
const return_alloca = current_function.return_alloca;
|
const return_alloca = current_function.return_alloca;
|
||||||
_ = module.create_store(.{
|
_ = module.create_store(.{
|
||||||
.source_value = return_value.llvm,
|
.source_value = return_value.llvm,
|
||||||
.destination_value = return_alloca,
|
.destination_value = return_alloca,
|
||||||
.source_type = return_type_abi.semantic_type,
|
.source_type = return_type_abi.semantic_type,
|
||||||
.destination_type = current_function_type.abi_return_type,
|
.destination_type = return_type_abi.semantic_type,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -2647,6 +2647,7 @@ const Converter = struct {
|
|||||||
integer_max,
|
integer_max,
|
||||||
int_from_enum,
|
int_from_enum,
|
||||||
int_from_pointer,
|
int_from_pointer,
|
||||||
|
pointer_cast,
|
||||||
select,
|
select,
|
||||||
trap,
|
trap,
|
||||||
truncate,
|
truncate,
|
||||||
@ -2825,6 +2826,30 @@ const Converter = struct {
|
|||||||
};
|
};
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
.pointer_cast => {
|
||||||
|
const ty = expected_type orelse converter.report_error();
|
||||||
|
if (ty.bb != .pointer) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
const source_value = converter.parse_value(module, null, .value);
|
||||||
|
converter.skip_space();
|
||||||
|
converter.expect_character(right_parenthesis);
|
||||||
|
if (source_value.type.bb != .pointer) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
if (ty == source_value.type) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.llvm = module.llvm.builder.create_pointer_cast(source_value.llvm, ty.llvm.handle),
|
||||||
|
.type = ty,
|
||||||
|
.bb = .instruction,
|
||||||
|
.lvalue = true,
|
||||||
|
.dereference_to_assign = false,
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
},
|
||||||
.select => {
|
.select => {
|
||||||
const condition_value = converter.parse_value(module, null, .value);
|
const condition_value = converter.parse_value(module, null, .value);
|
||||||
|
|
||||||
@ -3237,6 +3262,7 @@ const Converter = struct {
|
|||||||
if (field_count == struct_type.fields.len) {
|
if (field_count == struct_type.fields.len) {
|
||||||
converter.report_error();
|
converter.report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_ordered and is_constant) {
|
if (is_ordered and is_constant) {
|
||||||
const zero_fields = struct_type.fields[field_count..];
|
const zero_fields = struct_type.fields[field_count..];
|
||||||
const zero_field_values = field_value_buffer[field_count..][0..zero_fields.len];
|
const zero_field_values = field_value_buffer[field_count..][0..zero_fields.len];
|
||||||
@ -3567,9 +3593,6 @@ const Converter = struct {
|
|||||||
const appointee_type = variable.value.type.bb.pointer.type;
|
const appointee_type = variable.value.type.bb.pointer.type;
|
||||||
|
|
||||||
if (converter.consume_character_if_match(left_parenthesis)) {
|
if (converter.consume_character_if_match(left_parenthesis)) {
|
||||||
if (value_kind == .pointer) {
|
|
||||||
converter.report_error();
|
|
||||||
}
|
|
||||||
const call = converter.parse_call(module, variable.value);
|
const call = converter.parse_call(module, variable.value);
|
||||||
break :b call;
|
break :b call;
|
||||||
} else if (converter.consume_character_if_match('.')) {
|
} else if (converter.consume_character_if_match('.')) {
|
||||||
@ -3642,15 +3665,47 @@ const Converter = struct {
|
|||||||
.pointer => |pointer_type| {
|
.pointer => |pointer_type| {
|
||||||
const element_type = pointer_type.type;
|
const element_type = pointer_type.type;
|
||||||
if (converter.consume_character_if_match('&')) {
|
if (converter.consume_character_if_match('&')) {
|
||||||
const load = module.values.add();
|
const pointer_load = module.values.add();
|
||||||
load.* = .{
|
pointer_load.* = .{
|
||||||
.llvm = module.create_load(.{ .type = appointee_type, .value = variable.value.llvm }),
|
.llvm = module.create_load(.{ .type = appointee_type, .value = variable.value.llvm }),
|
||||||
.type = appointee_type,
|
.type = appointee_type,
|
||||||
.bb = .instruction,
|
.bb = .instruction,
|
||||||
.lvalue = false,
|
.lvalue = false,
|
||||||
.dereference_to_assign = false,
|
.dereference_to_assign = false,
|
||||||
};
|
};
|
||||||
break :b load;
|
switch (value_kind) {
|
||||||
|
.value => {
|
||||||
|
if (expected_type) |expected_ty| {
|
||||||
|
if (expected_ty == appointee_type) {
|
||||||
|
@trap();
|
||||||
|
} else {
|
||||||
|
if (appointee_type.bb == .pointer and appointee_type.bb.pointer.type == expected_ty) {
|
||||||
|
const load = module.values.add();
|
||||||
|
load.* = .{
|
||||||
|
.llvm = module.create_load(.{ .type = expected_ty, .value = pointer_load.llvm }),
|
||||||
|
.type = expected_ty,
|
||||||
|
.bb = .instruction,
|
||||||
|
.lvalue = false,
|
||||||
|
.dereference_to_assign = false,
|
||||||
|
};
|
||||||
|
break :b load;
|
||||||
|
} else {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.maybe_pointer, .pointer => {
|
||||||
|
if (expected_type) |expected_ty| {
|
||||||
|
_ = expected_ty;
|
||||||
|
@trap();
|
||||||
|
} else {
|
||||||
|
break :b pointer_load;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (element_type.bb) {
|
switch (element_type.bb) {
|
||||||
.structure => |*struct_type| {
|
.structure => |*struct_type| {
|
||||||
|
@ -408,3 +408,7 @@ test "integer_max" {
|
|||||||
test "unreachable" {
|
test "unreachable" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "pointer_cast" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
@ -101,6 +101,7 @@ pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destinat
|
|||||||
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildIntToPtr(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildIntToPtr(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildPtrToInt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildPtrToInt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
|
pub extern fn LLVMBuildPointerCast(builder: *llvm.Builder, value: *llvm.Value, ty: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildTrunc(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildTrunc(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
|
|
||||||
pub extern fn LLVMSetCurrentDebugLocation2(builder: *llvm.Builder, location: ?*llvm.DI.Location) void;
|
pub extern fn LLVMSetCurrentDebugLocation2(builder: *llvm.Builder, location: ?*llvm.DI.Location) void;
|
||||||
|
7
tests/pointer_cast.bbb
Normal file
7
tests/pointer_cast.bbb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>result: u32 = 0;
|
||||||
|
>pointer = &result;
|
||||||
|
>signed_ptr: &s32 = #pointer_cast(pointer);
|
||||||
|
return signed_ptr.&;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user