adding functions management
This commit is contained in:
@@ -251,13 +251,17 @@ variant: ?union(Variant) {
|
||||
source_location: usize,
|
||||
return_type: SpvWord,
|
||||
function_type: SpvWord,
|
||||
params: []const SpvWord,
|
||||
params: []SpvWord,
|
||||
},
|
||||
AccessChain: struct {
|
||||
target: SpvWord,
|
||||
value: Value,
|
||||
},
|
||||
FunctionParameter: struct {},
|
||||
FunctionParameter: struct {
|
||||
type_word: SpvWord,
|
||||
type: Type,
|
||||
value_ptr: ?*Value,
|
||||
},
|
||||
Label: struct {
|
||||
source_location: usize,
|
||||
},
|
||||
@@ -293,6 +297,7 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||
.Constant => |*c| c.value.deinit(allocator),
|
||||
.Variable => |*v| v.value.deinit(allocator),
|
||||
//.AccessChain => |*a| a.value.deinit(allocator),
|
||||
.Function => |f| allocator.free(f.params),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@@ -303,6 +308,8 @@ pub fn getValueTypeWord(self: *Self) RuntimeError!SpvWord {
|
||||
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |v| v.type_word,
|
||||
.Constant => |c| c.type_word,
|
||||
.AccessChain => |*a| a.target,
|
||||
.FunctionParameter => |p| p.type_word,
|
||||
else => RuntimeError.InvalidSpirV,
|
||||
};
|
||||
}
|
||||
@@ -311,6 +318,7 @@ pub fn getValueType(self: *Self) RuntimeError!Type {
|
||||
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |v| v.type,
|
||||
.Constant => |c| c.type,
|
||||
.FunctionParameter => |p| p.type,
|
||||
else => RuntimeError.InvalidSpirV,
|
||||
};
|
||||
}
|
||||
@@ -319,6 +327,8 @@ pub fn getValue(self: *Self) RuntimeError!*Value {
|
||||
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |*v| &v.value,
|
||||
.Constant => |*c| &c.value,
|
||||
.AccessChain => |*a| &a.value,
|
||||
.FunctionParameter => |*p| p.value_ptr orelse return RuntimeError.InvalidSpirV,
|
||||
else => RuntimeError.InvalidSpirV,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ pub const RuntimeError = error{
|
||||
pub const Function = struct {
|
||||
source_location: usize,
|
||||
result: *Result,
|
||||
ret: *Result,
|
||||
};
|
||||
|
||||
mod: *Module,
|
||||
@@ -35,6 +36,7 @@ it: WordIterator,
|
||||
/// Local deep copy of module's results to be able to run multiple runtimes concurrently
|
||||
results: []Result,
|
||||
|
||||
current_parameter_index: SpvWord,
|
||||
current_function: ?*Result,
|
||||
function_stack: std.ArrayList(Function),
|
||||
|
||||
@@ -49,6 +51,7 @@ pub fn init(allocator: std.mem.Allocator, module: *Module) RuntimeError!Self {
|
||||
}
|
||||
break :blk results;
|
||||
},
|
||||
.current_parameter_index = 0,
|
||||
.current_function = null,
|
||||
.function_stack = .empty,
|
||||
};
|
||||
@@ -103,6 +106,11 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
|
||||
switch (variant) {
|
||||
.Function => |f| {
|
||||
if (!self.it.jumpToSourceLocation(f.source_location)) return RuntimeError.InvalidEntryPoint;
|
||||
self.function_stack.append(allocator, .{
|
||||
.source_location = f.source_location,
|
||||
.result = entry_point_result,
|
||||
.ret = &self.results[f.return_type],
|
||||
}) catch return RuntimeError.OutOfMemory;
|
||||
},
|
||||
else => return RuntimeError.InvalidEntryPoint,
|
||||
}
|
||||
@@ -127,7 +135,7 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
|
||||
self.it = it_tmp;
|
||||
} else {
|
||||
self.it.did_jump = false;
|
||||
_ = it_tmp.skip();
|
||||
//_ = self.it.skip();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ pub const SetupDispatcher = block: {
|
||||
.Function = opFunction,
|
||||
.FunctionCall = autoSetupConstant,
|
||||
.FunctionEnd = opFunctionEnd,
|
||||
.FunctionParameter = opFunctionParameter,
|
||||
.IAdd = autoSetupConstant,
|
||||
.IEqual = autoSetupConstant,
|
||||
.IMul = autoSetupConstant,
|
||||
@@ -697,10 +698,55 @@ fn opFunction(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeErr
|
||||
rt.current_function = &rt.mod.results[id];
|
||||
}
|
||||
|
||||
fn opFunctionCall(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
_ = rt.it.skip();
|
||||
const ret = &rt.results[try rt.it.next()];
|
||||
const func = &rt.results[try rt.it.next()];
|
||||
|
||||
for ((func.variant orelse return RuntimeError.InvalidSpirV).Function.params) |param| {
|
||||
const arg = &rt.results[try rt.it.next()];
|
||||
(rt.results[param].variant orelse return RuntimeError.InvalidSpirV).FunctionParameter.value_ptr = try arg.getValue();
|
||||
}
|
||||
rt.function_stack.items[rt.function_stack.items.len - 1].source_location = rt.it.emitSourceLocation();
|
||||
const source_location = (func.variant orelse return RuntimeError.InvalidSpirV).Function.source_location;
|
||||
rt.function_stack.append(allocator, .{
|
||||
.source_location = source_location,
|
||||
.result = func,
|
||||
.ret = ret,
|
||||
}) catch return RuntimeError.OutOfMemory;
|
||||
if (!rt.it.jumpToSourceLocation(source_location)) return RuntimeError.InvalidSpirV;
|
||||
rt.current_parameter_index = 0;
|
||||
}
|
||||
|
||||
fn opFunctionEnd(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
rt.current_function = null;
|
||||
}
|
||||
|
||||
fn opFunctionParameter(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
const var_type = try rt.it.next();
|
||||
const id = try rt.it.next();
|
||||
|
||||
const target = &rt.mod.results[id];
|
||||
|
||||
const resolved = rt.mod.results[var_type].resolveType(rt.mod.results);
|
||||
const member_count = resolved.getMemberCounts();
|
||||
if (member_count == 0) {
|
||||
return RuntimeError.InvalidSpirV;
|
||||
}
|
||||
target.variant = .{
|
||||
.FunctionParameter = .{
|
||||
.type_word = var_type,
|
||||
.type = switch (resolved.variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Type => |t| @as(Result.Type, t),
|
||||
else => return RuntimeError.InvalidSpirV,
|
||||
},
|
||||
.value_ptr = null,
|
||||
},
|
||||
};
|
||||
((rt.current_function orelse return RuntimeError.InvalidSpirV).variant orelse return RuntimeError.InvalidSpirV).Function.params[rt.current_parameter_index] = id;
|
||||
rt.current_parameter_index += 1;
|
||||
}
|
||||
|
||||
fn opLabel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
const id = try rt.it.next();
|
||||
rt.mod.results[id].variant = .{
|
||||
@@ -714,20 +760,7 @@ fn opLoad(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
_ = rt.it.skip();
|
||||
const id = try rt.it.next();
|
||||
const ptr_id = try rt.it.next();
|
||||
copyValue(
|
||||
switch (rt.results[id].variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |*v| &v.value,
|
||||
.Constant => |*c| &c.value,
|
||||
.AccessChain => |*a| &a.value,
|
||||
else => return RuntimeError.InvalidSpirV,
|
||||
},
|
||||
switch (rt.results[ptr_id].variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |v| &v.value,
|
||||
.Constant => |c| &c.value,
|
||||
.AccessChain => |a| &a.value,
|
||||
else => return RuntimeError.InvalidSpirV,
|
||||
},
|
||||
);
|
||||
copyValue(try rt.results[id].getValue(), try rt.results[ptr_id].getValue());
|
||||
}
|
||||
|
||||
fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
@@ -775,7 +808,6 @@ fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runti
|
||||
}
|
||||
|
||||
fn opReturn(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
rt.last_return_id = null;
|
||||
_ = rt.function_stack.pop();
|
||||
if (rt.function_stack.getLastOrNull()) |function| {
|
||||
_ = rt.it.jumpToSourceLocation(function.source_location);
|
||||
@@ -787,6 +819,13 @@ fn opReturn(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
}
|
||||
|
||||
fn opReturnValue(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
if (rt.function_stack.getLastOrNull()) |function| {
|
||||
var ret_res = rt.results[try rt.it.next()];
|
||||
copyValue(try function.ret.getValue(), try ret_res.getValue());
|
||||
} else {
|
||||
return RuntimeError.InvalidSpirV; // No current function ???
|
||||
}
|
||||
|
||||
_ = rt.function_stack.pop();
|
||||
if (rt.function_stack.getLastOrNull()) |function| {
|
||||
_ = rt.it.jumpToSourceLocation(function.source_location);
|
||||
@@ -824,20 +863,7 @@ fn opSourceExtension(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Run
|
||||
fn opStore(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
const ptr_id = try rt.it.next();
|
||||
const val_id = try rt.it.next();
|
||||
copyValue(
|
||||
switch (rt.results[ptr_id].variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |*v| &v.value,
|
||||
.Constant => |*c| &c.value,
|
||||
.AccessChain => |*a| &a.value,
|
||||
else => return RuntimeError.InvalidSpirV,
|
||||
},
|
||||
switch (rt.results[val_id].variant orelse return RuntimeError.InvalidSpirV) {
|
||||
.Variable => |v| &v.value,
|
||||
.Constant => |c| &c.value,
|
||||
.AccessChain => |a| &a.value,
|
||||
else => return RuntimeError.InvalidSpirV,
|
||||
},
|
||||
);
|
||||
copyValue(try rt.results[ptr_id].getValue(), try rt.results[val_id].getValue());
|
||||
}
|
||||
|
||||
fn opTypeBool(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||
|
||||
Reference in New Issue
Block a user