Basic call with no arguments
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 36s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 37s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 44s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 58s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 33s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 34s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 40s
CI / ci (Debug, ubuntu-latest) (push) Successful in 55s
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (pull_request) Successful in 36s
CI / ci (ReleaseSmall, ubuntu-latest) (pull_request) Successful in 37s
CI / ci (ReleaseSafe, ubuntu-latest) (pull_request) Successful in 44s
CI / ci (Debug, ubuntu-latest) (pull_request) Successful in 58s
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 33s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 34s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 40s
CI / ci (Debug, ubuntu-latest) (push) Successful in 55s
This commit is contained in:
parent
3309329911
commit
143fa2d03b
@ -485,6 +485,11 @@ const Binary = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Call = struct {
|
||||||
|
callable: *Value,
|
||||||
|
arguments: []const *Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Value = struct {
|
pub const Value = struct {
|
||||||
bb: union(enum) {
|
bb: union(enum) {
|
||||||
function: Function,
|
function: Function,
|
||||||
@ -495,6 +500,7 @@ pub const Value = struct {
|
|||||||
local,
|
local,
|
||||||
intrinsic: Intrinsic,
|
intrinsic: Intrinsic,
|
||||||
dereference: *Value,
|
dereference: *Value,
|
||||||
|
call: Call,
|
||||||
},
|
},
|
||||||
type: ?*Type = null,
|
type: ?*Type = null,
|
||||||
llvm: ?*llvm.Value = null,
|
llvm: ?*llvm.Value = null,
|
||||||
@ -652,7 +658,7 @@ pub const Scope = struct {
|
|||||||
column: u32,
|
column: u32,
|
||||||
llvm: ?*llvm.DI.Scope = null,
|
llvm: ?*llvm.DI.Scope = null,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
parent: ?*Scope = null,
|
parent: ?*Scope,
|
||||||
|
|
||||||
pub const Kind = enum {
|
pub const Kind = enum {
|
||||||
global,
|
global,
|
||||||
@ -668,7 +674,7 @@ pub const LexicalBlock = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Function = struct {
|
pub const Function = struct {
|
||||||
arguments: Local.Buffer,
|
arguments: []*Local,
|
||||||
attributes: Attributes,
|
attributes: Attributes,
|
||||||
main_block: *LexicalBlock,
|
main_block: *LexicalBlock,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
@ -1707,10 +1713,24 @@ pub const Module = struct {
|
|||||||
const variable = blk: while (scope_it) |scope| : (scope_it = scope.parent) {
|
const variable = blk: while (scope_it) |scope| : (scope_it = scope.parent) {
|
||||||
switch (scope.kind) {
|
switch (scope.kind) {
|
||||||
.global => {
|
.global => {
|
||||||
@trap();
|
const m: *Module = @fieldParentPtr("scope", scope);
|
||||||
|
assert(m == module);
|
||||||
|
for (module.globals.get_slice()) |*global| {
|
||||||
|
if (lib.string.equal(global.variable.name, identifier)) {
|
||||||
|
break :blk &global.variable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(scope.parent == null);
|
||||||
},
|
},
|
||||||
.function => {
|
.function => {
|
||||||
@trap();
|
const function: *Function = @fieldParentPtr("scope", scope);
|
||||||
|
for (function.arguments) |argument| {
|
||||||
|
if (lib.string.equal(argument.variable.name, identifier)) {
|
||||||
|
break :blk &argument.variable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(scope.parent != null);
|
||||||
},
|
},
|
||||||
.local => {
|
.local => {
|
||||||
const block: *LexicalBlock = @fieldParentPtr("scope", scope);
|
const block: *LexicalBlock = @fieldParentPtr("scope", scope);
|
||||||
@ -1719,6 +1739,7 @@ pub const Module = struct {
|
|||||||
break :blk &local.variable;
|
break :blk &local.variable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(scope.parent != null);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1886,9 +1907,41 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn rule_after_call(noalias module: *Module, value_builder: Value.Builder) *Value {
|
fn rule_after_call(noalias module: *Module, value_builder: Value.Builder) *Value {
|
||||||
_ = module;
|
const may_be_callable = value_builder.left orelse module.report_error();
|
||||||
_ = value_builder;
|
assert(value_builder.token == .@"(");
|
||||||
@trap();
|
var semantic_argument_count: u32 = 0;
|
||||||
|
_ = &semantic_argument_count;
|
||||||
|
var semantic_argument_buffer: [64]*Value = undefined;
|
||||||
|
_ = &semantic_argument_buffer;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
module.skip_space();
|
||||||
|
|
||||||
|
if (module.consume_character_if_match(right_parenthesis)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const argument = module.parse_value(.{});
|
||||||
|
// const argument_index = semantic_argument_count;
|
||||||
|
// semantic_argument_buffer[argument_index] = argument;
|
||||||
|
// semantic_argument_count = argument_index + 1;
|
||||||
|
@trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const arguments: []const *Value = if (semantic_argument_count != 0) {
|
||||||
|
@trap();
|
||||||
|
} else &.{};
|
||||||
|
|
||||||
|
const call = module.values.add();
|
||||||
|
call.* = .{
|
||||||
|
.bb = .{
|
||||||
|
.call = .{
|
||||||
|
.arguments = arguments,
|
||||||
|
.callable = may_be_callable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_anonymous_struct_pair(module: *Module, pair: [2]*Type) *Type {
|
pub fn get_anonymous_struct_pair(module: *Module, pair: [2]*Type) *Type {
|
||||||
@ -2070,12 +2123,13 @@ pub const Module = struct {
|
|||||||
storage.bb = .{
|
storage.bb = .{
|
||||||
.function = .{
|
.function = .{
|
||||||
.main_block = undefined,
|
.main_block = undefined,
|
||||||
.arguments = .initialize(),
|
.arguments = &.{},
|
||||||
.attributes = .{},
|
.attributes = .{},
|
||||||
.scope = .{
|
.scope = .{
|
||||||
.kind = .function,
|
.kind = .function,
|
||||||
.line = global_line,
|
.line = global_line,
|
||||||
.column = global_column,
|
.column = global_column,
|
||||||
|
.parent = &module.scope,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -2157,7 +2211,7 @@ pub const Module = struct {
|
|||||||
switch (global.variable.storage.?.bb) {
|
switch (global.variable.storage.?.bb) {
|
||||||
.function => {
|
.function => {
|
||||||
const function_type = &global.variable.storage.?.type.?.bb.pointer.type.bb.function;
|
const function_type = &global.variable.storage.?.type.?.bb.pointer.type.bb.function;
|
||||||
const argument_variables = global.variable.storage.?.bb.function.arguments.get_slice();
|
const argument_variables = global.variable.storage.?.bb.function.arguments;
|
||||||
function_type.argument_abis = module.arena.allocate(Abi.Information, argument_variables.len);
|
function_type.argument_abis = module.arena.allocate(Abi.Information, argument_variables.len);
|
||||||
|
|
||||||
const resolved_calling_convention = function_type.calling_convention.resolve(module.target);
|
const resolved_calling_convention = function_type.calling_convention.resolve(module.target);
|
||||||
@ -2323,7 +2377,7 @@ pub const Module = struct {
|
|||||||
//semantic_arguments,
|
//semantic_arguments,
|
||||||
function_type.argument_abis, argument_variables, 0..) |
|
function_type.argument_abis, argument_variables, 0..) |
|
||||||
//semantic_argument,
|
//semantic_argument,
|
||||||
argument_abi, *argument_variable, argument_index| {
|
argument_abi, argument_variable, argument_index| {
|
||||||
const abi_arguments = llvm_abi_arguments[argument_abi.abi_start..][0..argument_abi.abi_count];
|
const abi_arguments = llvm_abi_arguments[argument_abi.abi_start..][0..argument_abi.abi_count];
|
||||||
assert(argument_abi.flags.kind == .ignore or argument_abi.abi_count != 0);
|
assert(argument_abi.flags.kind == .ignore or argument_abi.abi_count != 0);
|
||||||
const argument_abi_kind = argument_abi.flags.kind;
|
const argument_abi_kind = argument_abi.flags.kind;
|
||||||
@ -2796,6 +2850,19 @@ pub const Module = struct {
|
|||||||
};
|
};
|
||||||
break :blk result;
|
break :blk result;
|
||||||
},
|
},
|
||||||
|
.call => |call| blk: {
|
||||||
|
const llvm_callable = switch (call.callable.bb) {
|
||||||
|
.variable_reference => |variable| variable.storage.?.llvm.?,
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
const function_type = switch (call.callable.bb) {
|
||||||
|
.variable_reference => |variable| variable.storage.?.type.?.bb.pointer.type,
|
||||||
|
else => @trap(),
|
||||||
|
};
|
||||||
|
const llvm_function_type = function_type.resolve(module).handle;
|
||||||
|
const llvm_call = module.llvm.builder.create_call(llvm_function_type.to_function(), llvm_callable, &.{});
|
||||||
|
break :blk llvm_call;
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2807,9 +2874,9 @@ pub const Module = struct {
|
|||||||
assert(value.llvm == null);
|
assert(value.llvm == null);
|
||||||
|
|
||||||
// If a result type exists, then do the analysis against it
|
// 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 (value.bb) {
|
||||||
.integer => |integer| switch (value.bb) {
|
.constant_integer => |constant_integer| switch (expected_type.bb) {
|
||||||
.constant_integer => |constant_integer| switch (constant_integer.signed) {
|
.integer => |integer| switch (constant_integer.signed) {
|
||||||
true => {
|
true => {
|
||||||
if (!integer.signed) {
|
if (!integer.signed) {
|
||||||
module.report_error();
|
module.report_error();
|
||||||
@ -2826,75 +2893,81 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.unary => |unary| {
|
else => @trap(),
|
||||||
switch (unary.id) {
|
},
|
||||||
.@"+" => @trap(),
|
.unary => |unary| {
|
||||||
.@"-" => {
|
switch (unary.id) {
|
||||||
module.analyze_value_type(function, unary.value, analysis);
|
.@"+" => @trap(),
|
||||||
if (!unary.value.type.?.is_signed()) {
|
.@"-" => {
|
||||||
module.report_error();
|
module.analyze_value_type(function, unary.value, analysis);
|
||||||
}
|
if (!unary.value.type.?.is_signed()) {
|
||||||
|
|
||||||
assert(expected_type == unary.value.type);
|
|
||||||
},
|
|
||||||
.@"&" => @trap(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.binary => |binary| {
|
|
||||||
const is_boolean = binary.id.is_boolean();
|
|
||||||
|
|
||||||
const boolean_type = module.integer_type(1, false);
|
|
||||||
|
|
||||||
if (is_boolean and expected_type != boolean_type) {
|
|
||||||
module.report_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.analyze_value_type(function, binary.left, .{
|
|
||||||
.type = if (is_boolean) null else expected_type,
|
|
||||||
});
|
|
||||||
|
|
||||||
module.analyze_value_type(function, binary.right, .{
|
|
||||||
.type = binary.left.type,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.variable_reference => |variable| {
|
|
||||||
if (variable.type != expected_type) {
|
|
||||||
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();
|
module.report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(expected_type == unary.value.type);
|
||||||
},
|
},
|
||||||
.truncate => |value_to_truncate| {
|
.@"&" => @trap(),
|
||||||
module.analyze_value_type(function, value_to_truncate, .{});
|
}
|
||||||
if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) {
|
},
|
||||||
module.report_error();
|
.binary => |binary| {
|
||||||
}
|
const is_boolean = binary.id.is_boolean();
|
||||||
},
|
|
||||||
else => @trap(),
|
const boolean_type = module.integer_type(1, false);
|
||||||
},
|
|
||||||
.dereference => |dereferenceable_value| {
|
if (is_boolean and expected_type != boolean_type) {
|
||||||
module.analyze_value_type(function, dereferenceable_value, .{});
|
module.report_error();
|
||||||
if (dereferenceable_value.type.?.bb != .pointer) {
|
}
|
||||||
|
|
||||||
|
module.analyze_value_type(function, binary.left, .{
|
||||||
|
.type = if (is_boolean) null else expected_type,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.analyze_value_type(function, binary.right, .{
|
||||||
|
.type = binary.left.type,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.variable_reference => |variable| {
|
||||||
|
if (variable.type != expected_type) {
|
||||||
|
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();
|
module.report_error();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
if (dereferenceable_value.type.?.bb.pointer.type != expected_type) {
|
.truncate => |value_to_truncate| {
|
||||||
|
module.analyze_value_type(function, value_to_truncate, .{});
|
||||||
|
if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) {
|
||||||
module.report_error();
|
module.report_error();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
},
|
},
|
||||||
|
.dereference => |dereferenceable_value| {
|
||||||
|
module.analyze_value_type(function, dereferenceable_value, .{});
|
||||||
|
if (dereferenceable_value.type.?.bb != .pointer) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dereferenceable_value.type.?.bb.pointer.type != expected_type) {
|
||||||
|
module.report_error();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.call => |call| {
|
||||||
|
module.analyze_value_type(function, call.callable, .{});
|
||||||
|
for (call.arguments) |argument| {
|
||||||
|
module.analyze_value_type(function, argument, .{});
|
||||||
|
}
|
||||||
|
},
|
||||||
else => @trap(),
|
else => @trap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4352,6 +4425,7 @@ pub fn compile(arena: *Arena, options: Options) void {
|
|||||||
.kind = .global,
|
.kind = .global,
|
||||||
.column = 0,
|
.column = 0,
|
||||||
.line = 0,
|
.line = 0,
|
||||||
|
.parent = null,
|
||||||
},
|
},
|
||||||
.name = options.name,
|
.name = options.name,
|
||||||
.path = options.path,
|
.path = options.path,
|
||||||
|
@ -188,8 +188,10 @@ const names = &[_][]const u8{
|
|||||||
"minimal_stack_arithmetic3",
|
"minimal_stack_arithmetic3",
|
||||||
"extend",
|
"extend",
|
||||||
"stack_negation",
|
"stack_negation",
|
||||||
"basic_pointer",
|
"stack_add",
|
||||||
"integer_max",
|
"integer_max",
|
||||||
"integer_hex",
|
"integer_hex",
|
||||||
|
"basic_pointer",
|
||||||
|
"basic_call",
|
||||||
// "pointer",
|
// "pointer",
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user