Basic while
All checks were successful
All checks were successful
This commit is contained in:
parent
c09967697c
commit
30b0b2a259
@ -524,6 +524,10 @@ pub const Statement = struct {
|
||||
if_block: *LexicalBlock,
|
||||
else_block: ?*LexicalBlock,
|
||||
},
|
||||
@"while": struct {
|
||||
condition: *Value,
|
||||
block: *LexicalBlock,
|
||||
},
|
||||
},
|
||||
line: u32,
|
||||
column: u32,
|
||||
@ -558,6 +562,13 @@ const Unary = struct {
|
||||
@"+",
|
||||
@"&",
|
||||
@"!",
|
||||
|
||||
pub fn is_boolean(id: Id) bool {
|
||||
return switch (id) {
|
||||
.@"+", .@"-", .@"&" => false,
|
||||
.@"!" => true,
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -653,7 +664,7 @@ pub const Value = struct {
|
||||
extend: *Value,
|
||||
integer_max: *Type,
|
||||
int_from_enum: *Value,
|
||||
int_from_pointer,
|
||||
int_from_pointer: *Value,
|
||||
pointer_cast: *Value,
|
||||
select,
|
||||
trap,
|
||||
@ -2112,7 +2123,28 @@ pub const Module = struct {
|
||||
};
|
||||
},
|
||||
.@"while" => {
|
||||
@trap();
|
||||
module.skip_space();
|
||||
|
||||
module.expect_character(left_parenthesis);
|
||||
module.skip_space();
|
||||
|
||||
const condition = module.parse_value(.{});
|
||||
|
||||
module.skip_space();
|
||||
module.expect_character(right_parenthesis);
|
||||
|
||||
module.skip_space();
|
||||
|
||||
const while_block = module.parse_block();
|
||||
|
||||
require_semicolon = false;
|
||||
|
||||
break :blk .{
|
||||
.@"while" = .{
|
||||
.condition = condition,
|
||||
.block = while_block,
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
} else {
|
||||
@ -2391,6 +2423,20 @@ pub const Module = struct {
|
||||
},
|
||||
};
|
||||
},
|
||||
.int_from_pointer => blk: {
|
||||
module.skip_space();
|
||||
module.expect_character(left_parenthesis);
|
||||
module.skip_space();
|
||||
const arg_value = module.parse_value(.{});
|
||||
module.expect_character(right_parenthesis);
|
||||
break :blk .{
|
||||
.bb = .{
|
||||
.intrinsic = .{
|
||||
.int_from_pointer = arg_value,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
.pointer_cast => blk: {
|
||||
module.skip_space();
|
||||
module.expect_character(left_parenthesis);
|
||||
@ -3888,6 +3934,16 @@ pub const Module = struct {
|
||||
module.report_error();
|
||||
}
|
||||
},
|
||||
.int_from_pointer => |pointer_value| {
|
||||
module.analyze_value_type(function, pointer_value, .{});
|
||||
assert(pointer_value.type != null);
|
||||
if (pointer_value.type.?.bb != .pointer) {
|
||||
module.report_error();
|
||||
}
|
||||
if (expected_type != module.integer_type(64, false)) {
|
||||
module.report_error();
|
||||
}
|
||||
},
|
||||
.pointer_cast => |pointer_value| {
|
||||
if (expected_type.bb != .pointer) {
|
||||
module.report_error();
|
||||
@ -4016,7 +4072,10 @@ pub const Module = struct {
|
||||
const value_type = if (analysis.type) |expected_type| expected_type else switch (value.bb) {
|
||||
.unary => |unary| blk: {
|
||||
module.analyze_value_type(function, unary.value, .{});
|
||||
break :blk unary.value.type.?;
|
||||
break :blk switch (unary.id.is_boolean()) {
|
||||
true => module.integer_type(1, false),
|
||||
false => unary.value.type.?,
|
||||
};
|
||||
},
|
||||
.binary => |binary| blk: {
|
||||
if (binary.left.bb == .constant_integer and binary.right.bb == .constant_integer) {
|
||||
@ -4210,7 +4269,13 @@ pub const Module = struct {
|
||||
module.emit_value(function, unary.value);
|
||||
break :b module.llvm.builder.create_not(unary.value.llvm.?);
|
||||
},
|
||||
false => @trap(),
|
||||
false => switch (unary.value.type.?.bb) {
|
||||
.pointer => b: {
|
||||
module.emit_value(function, unary.value);
|
||||
break :b module.llvm.builder.create_integer_compare(.eq, unary.value.llvm.?, unary.value.type.?.llvm.handle.?.get_zero().to_value());
|
||||
},
|
||||
else => @trap(),
|
||||
},
|
||||
},
|
||||
else => @trap(),
|
||||
},
|
||||
@ -4263,6 +4328,19 @@ pub const Module = struct {
|
||||
false => module.llvm.builder.create_integer_compare(.ule, left, right),
|
||||
},
|
||||
},
|
||||
.pointer => |pointer| switch (binary.id) {
|
||||
.@"+" => module.llvm.builder.create_gep(.{
|
||||
.type = pointer.type.llvm.handle.?,
|
||||
.aggregate = left,
|
||||
.indices = &.{right},
|
||||
}),
|
||||
.@"-" => module.llvm.builder.create_gep(.{
|
||||
.type = pointer.type.llvm.handle.?,
|
||||
.aggregate = left,
|
||||
.indices = &.{module.negate_llvm_value(right, binary.right.is_constant())},
|
||||
}),
|
||||
else => module.report_error(),
|
||||
},
|
||||
else => @trap(),
|
||||
};
|
||||
break :blk result;
|
||||
@ -4337,6 +4415,11 @@ pub const Module = struct {
|
||||
module.emit_value(function, enum_value);
|
||||
break :blk enum_value.llvm.?;
|
||||
},
|
||||
.int_from_pointer => |pointer_value| blk: {
|
||||
module.emit_value(function, pointer_value);
|
||||
const int = module.llvm.builder.create_ptr_to_int(pointer_value.llvm.?, value_type.llvm.handle.?);
|
||||
break :blk int;
|
||||
},
|
||||
.pointer_cast => |pointer_value| blk: {
|
||||
module.emit_value(function, pointer_value);
|
||||
break :blk pointer_value.llvm.?;
|
||||
@ -4979,6 +5062,7 @@ pub const Module = struct {
|
||||
}
|
||||
|
||||
pub fn analyze_block(module: *Module, function: *Global, block: *LexicalBlock) void {
|
||||
const llvm_function = function.variable.storage.?.llvm.?.to_function();
|
||||
if (module.has_debug_info) {
|
||||
const lexical_block = module.llvm.di_builder.create_lexical_block(block.scope.parent.?.llvm.?, module.llvm.file, block.scope.line, block.scope.column);
|
||||
block.scope.llvm = lexical_block.to_scope();
|
||||
@ -5212,7 +5296,6 @@ pub const Module = struct {
|
||||
module.analyze(function, expression_value, .{});
|
||||
},
|
||||
.@"if" => |if_statement| {
|
||||
const llvm_function = function.variable.storage.?.llvm.?.to_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 exit_block = module.llvm.context.create_basic_block("if.end", null);
|
||||
@ -5222,6 +5305,7 @@ pub const Module = struct {
|
||||
.integer => |integer| if (integer.bit_count != 1) {
|
||||
module.report_error();
|
||||
} else if_statement.condition.llvm.?,
|
||||
.pointer => module.llvm.builder.create_integer_compare(.ne, if_statement.condition.llvm.?, if_statement.condition.type.?.llvm.handle.?.get_zero().to_value()),
|
||||
else => @trap(),
|
||||
};
|
||||
|
||||
@ -5277,6 +5361,43 @@ pub const Module = struct {
|
||||
exit_block.delete();
|
||||
}
|
||||
},
|
||||
.@"while" => |while_loop| {
|
||||
const loop_entry_block = module.llvm.context.create_basic_block("while.entry", llvm_function);
|
||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||
module.llvm.builder.position_at_end(loop_entry_block);
|
||||
|
||||
module.analyze(function, while_loop.condition, .{});
|
||||
|
||||
const boolean_type = module.integer_type(1, false);
|
||||
const condition_value = switch (while_loop.condition.type == boolean_type) {
|
||||
true => while_loop.condition.llvm.?,
|
||||
false => switch (while_loop.condition.type.?.bb) {
|
||||
.integer => module.llvm.builder.create_integer_compare(.ne, while_loop.condition.llvm.?, while_loop.condition.type.?.llvm.handle.?.to_integer().get_constant(0, @intFromBool(false)).to_value()),
|
||||
else => @trap(),
|
||||
},
|
||||
};
|
||||
|
||||
const loop_body_block = module.llvm.context.create_basic_block("while.body", llvm_function);
|
||||
const loop_end_block = module.llvm.context.create_basic_block("while.end", llvm_function);
|
||||
_ = module.llvm.builder.create_conditional_branch(condition_value, loop_body_block, loop_end_block);
|
||||
module.llvm.builder.position_at_end(loop_body_block);
|
||||
|
||||
module.analyze_block(function, while_loop.block);
|
||||
|
||||
if (module.llvm.builder.get_insert_block() != null) {
|
||||
_ = module.llvm.builder.create_branch(loop_entry_block);
|
||||
}
|
||||
|
||||
if (loop_body_block.to_value().use_empty()) {
|
||||
@trap();
|
||||
}
|
||||
|
||||
if (loop_end_block.to_value().use_empty()) {
|
||||
@trap();
|
||||
}
|
||||
|
||||
module.llvm.builder.position_at_end(loop_end_block);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5399,7 +5520,7 @@ pub const Module = struct {
|
||||
};
|
||||
if (module.has_debug_info) {
|
||||
module.llvm.builder.set_current_debug_location(statement_debug_location);
|
||||
const debug_type = resolved_type.llvm.debug.?;
|
||||
const debug_type = resolved_type.resolve(module).debug;
|
||||
const always_preserve = true;
|
||||
// TODO:
|
||||
const alignment = 0;
|
||||
@ -5505,12 +5626,13 @@ pub const Module = struct {
|
||||
assert(options.source_type != options.destination_type);
|
||||
const source_size = options.source_type.get_bit_size();
|
||||
const destination_size = options.destination_type.get_bit_size();
|
||||
const llvm_destination_type = options.destination_type.resolve(module).handle;
|
||||
const result = switch (source_size < destination_size) {
|
||||
true => switch (options.source_type.is_signed()) {
|
||||
true => module.llvm.builder.create_sign_extend(options.value, options.destination_type.llvm.handle.?),
|
||||
false => module.llvm.builder.create_zero_extend(options.value, options.destination_type.llvm.handle.?),
|
||||
true => module.llvm.builder.create_sign_extend(options.value, llvm_destination_type),
|
||||
false => module.llvm.builder.create_zero_extend(options.value, llvm_destination_type),
|
||||
},
|
||||
false => module.llvm.builder.create_truncate(options.value, options.destination_type.llvm.handle.?),
|
||||
false => module.llvm.builder.create_truncate(options.value, llvm_destination_type),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
@ -211,4 +211,6 @@ const names = &[_][]const u8{
|
||||
"basic_slice",
|
||||
"basic_string",
|
||||
"basic_varargs",
|
||||
"basic_while",
|
||||
"not_pointer",
|
||||
};
|
||||
|
7
tests/not_pointer.bbb
Normal file
7
tests/not_pointer.bbb
Normal file
@ -0,0 +1,7 @@
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>a: s32 = 0;
|
||||
>ptr = &a;
|
||||
>b = !ptr;
|
||||
return #extend(b);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user