instruction encoding
This commit is contained in:
parent
c7bcfa1de9
commit
d391898b95
@ -303,6 +303,7 @@ pub const Module = struct {
|
|||||||
calls: BlockList(Call) = .{},
|
calls: BlockList(Call) = .{},
|
||||||
argument_list: BlockList(ArgumentList) = .{},
|
argument_list: BlockList(ArgumentList) = .{},
|
||||||
returns: BlockList(Return) = .{},
|
returns: BlockList(Return) = .{},
|
||||||
|
entry_point: ?u32 = null,
|
||||||
|
|
||||||
pub const Descriptor = struct {
|
pub const Descriptor = struct {
|
||||||
main_package_path: []const u8,
|
main_package_path: []const u8,
|
||||||
|
@ -27,7 +27,7 @@ pub const Result = struct {
|
|||||||
},
|
},
|
||||||
entry_point: u32 = 0,
|
entry_point: u32 = 0,
|
||||||
|
|
||||||
fn create() !Result {
|
pub fn create() !Result {
|
||||||
return Result{
|
return Result{
|
||||||
.sections = .{
|
.sections = .{
|
||||||
.text = .{ .content = try mmap(page_size, .{ .executable = true }) },
|
.text = .{ .content = try mmap(page_size, .{ .executable = true }) },
|
||||||
@ -82,14 +82,6 @@ pub const Result = struct {
|
|||||||
image.sections.text.index += 1;
|
image.sections.text.index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn appendOnlyOpcodeSkipInstructionBytes(image: *Result, instruction: Instruction) void {
|
|
||||||
// const instruction_descriptor = instruction_descriptors.get(instruction);
|
|
||||||
// assert(instruction_descriptor.opcode_byte_count == instruction_descriptor.operand_offset);
|
|
||||||
// image.appendCode(instruction_descriptor.getOpcode());
|
|
||||||
//
|
|
||||||
// image.sections.text.index += instruction_descriptor.size - instruction_descriptor.opcode_byte_count;
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn getEntryPoint(image: *const Result, comptime FunctionType: type) *const FunctionType {
|
fn getEntryPoint(image: *const Result, comptime FunctionType: type) *const FunctionType {
|
||||||
comptime {
|
comptime {
|
||||||
assert(@typeInfo(FunctionType) == .Fn);
|
assert(@typeInfo(FunctionType) == .Fn);
|
||||||
@ -127,79 +119,13 @@ pub fn get(comptime arch: std.Target.Cpu.Arch) type {
|
|||||||
.x86_64 => @import("x86_64.zig"),
|
.x86_64 => @import("x86_64.zig"),
|
||||||
else => @compileError("Architecture not supported"),
|
else => @compileError("Architecture not supported"),
|
||||||
};
|
};
|
||||||
const Instruction = backend.Instruction;
|
|
||||||
_ = Instruction;
|
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
pub fn initialize(allocator: Allocator, intermediate: *ir.Result) !void {
|
pub fn initialize(allocator: Allocator, intermediate: *ir.Result) !void {
|
||||||
var result = try Result.create();
|
std.debug.print("Entry point: {}\n", .{intermediate.entry_point});
|
||||||
var mir = try backend.MIR.generate(allocator, intermediate);
|
var mir = try backend.MIR.generate(allocator, intermediate);
|
||||||
try mir.allocateRegisters(allocator, intermediate);
|
try mir.allocateRegisters(allocator, intermediate);
|
||||||
// var function_iterator = intermediate.functions.iterator();
|
const result = try mir.encode(intermediate);
|
||||||
// const IS = InstructionSelector(Instruction);
|
|
||||||
// var instruction_selector = IS{
|
|
||||||
// .functions = try ArrayList(IS.Function).initCapacity(allocator, intermediate.functions.len),
|
|
||||||
// .allocator = allocator,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// while (function_iterator.next()) |ir_function| {
|
|
||||||
// const function = instruction_selector.functions.addOneAssumeCapacity();
|
|
||||||
// function.* = .{};
|
|
||||||
// try function.block_map.ensureTotalCapacity(allocator, @intCast(ir_function.blocks.items.len));
|
|
||||||
// for (ir_function.blocks.items, 0..) |block_index, index| {
|
|
||||||
// function.block_map.putAssumeCapacity(block_index, @intCast(index));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (ir_function.blocks.items) |block_index| {
|
|
||||||
// const block = intermediate.blocks.get(block_index);
|
|
||||||
// for (block.instructions.items) |instruction_index| {
|
|
||||||
// const instruction = intermediate.instructions.get(instruction_index).*;
|
|
||||||
// try backend.selectInstruction(&instruction_selector, function, intermediate, instruction);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // function.block_byte_counts.appendAssumeCapacity(function.block_byte_count);
|
|
||||||
// // function.byte_count += function.block_byte_count;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (instruction_selector.functions.items) |function| {
|
|
||||||
// for (function.instructions.items) |instruction| backend.emitInstruction(&result, instruction, intermediate);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (instruction_selector.functions.items) |function| {
|
|
||||||
// var fix_size: bool = false;
|
|
||||||
// _ = fix_size;
|
|
||||||
// for (function.relocations.items) |instruction_index| {
|
|
||||||
// const instruction = function.instructions.items[instruction_index];
|
|
||||||
// const relative = instruction.jmp_rel_8;
|
|
||||||
// const source_block = relative.source;
|
|
||||||
// const destination_block = relative.destination;
|
|
||||||
// const source_offset = function.block_offsets.items[source_block];
|
|
||||||
// const destination_offset = function.block_offsets.items[destination_block];
|
|
||||||
// std.debug.print("Source offset: {}. Destination: {}\n", .{ source_offset, destination_offset });
|
|
||||||
// const instruction_descriptor = instruction_descriptors.get(relative.instruction);
|
|
||||||
// const instruction_offset = source_offset + relative.block_offset;
|
|
||||||
// const really_source_offset = instruction_offset + instruction_descriptor.size;
|
|
||||||
// const displacement = @as(i64, destination_offset) - @as(i64, really_source_offset);
|
|
||||||
//
|
|
||||||
// const operands = instruction_descriptor.getOperands();
|
|
||||||
// switch (operands.len) {
|
|
||||||
// 1 => switch (operands[0].size) {
|
|
||||||
// @sizeOf(u8) => {
|
|
||||||
// if (displacement >= std.math.minInt(i8) and displacement <= std.math.maxInt(i8)) {
|
|
||||||
// const writer_index = instruction_offset + instruction_descriptor.operand_offset;
|
|
||||||
// std.debug.print("Instruction offset: {}. Operand offset: {}. Writer index: {}. displacement: {}\n", .{ instruction_offset, instruction_descriptor.operand_offset, writer_index, displacement });
|
|
||||||
// result.sections.text.content[writer_index] = @bitCast(@as(i8, @intCast(displacement)));
|
|
||||||
// } else {
|
|
||||||
// unreachable;
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// else => unreachable,
|
|
||||||
// },
|
|
||||||
// else => unreachable,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const text_section = result.sections.text.content[0..result.sections.text.index];
|
const text_section = result.sections.text.content[0..result.sections.text.index];
|
||||||
for (text_section) |byte| {
|
for (text_section) |byte| {
|
||||||
|
@ -25,6 +25,7 @@ pub const Result = struct {
|
|||||||
syscalls: BlockList(Syscall) = .{},
|
syscalls: BlockList(Syscall) = .{},
|
||||||
values: BlockList(Value) = .{},
|
values: BlockList(Value) = .{},
|
||||||
stack_references: BlockList(StackReference) = .{},
|
stack_references: BlockList(StackReference) = .{},
|
||||||
|
entry_point: u32 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn initialize(compilation: *Compilation, module: *Module, package: *Package, main_file: Compilation.Type.Index) !Result {
|
pub fn initialize(compilation: *Compilation, module: *Module, package: *Package, main_file: Compilation.Type.Index) !Result {
|
||||||
@ -38,6 +39,8 @@ pub fn initialize(compilation: *Compilation, module: *Module, package: *Package,
|
|||||||
.module = module,
|
.module = module,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
builder.ir.entry_point = module.entry_point orelse unreachable;
|
||||||
|
|
||||||
while (function_iterator.next()) |sema_function| {
|
while (function_iterator.next()) |sema_function| {
|
||||||
const function_index = try builder.buildFunction(sema_function);
|
const function_index = try builder.buildFunction(sema_function);
|
||||||
try builder.optimizeFunction(function_index);
|
try builder.optimizeFunction(function_index);
|
||||||
@ -284,10 +287,29 @@ pub const Builder = struct {
|
|||||||
for (basic_block.instructions.items) |instruction_index| {
|
for (basic_block.instructions.items) |instruction_index| {
|
||||||
did_something = did_something or try builder.removeUnreachablePhis(reachable_blocks, instruction_index);
|
did_something = did_something or try builder.removeUnreachablePhis(reachable_blocks, instruction_index);
|
||||||
did_something = did_something or try builder.removeTrivialPhis(instruction_index);
|
did_something = did_something or try builder.removeTrivialPhis(instruction_index);
|
||||||
did_something = did_something or try builder.removeCopies(instruction_index);
|
const copy = try builder.removeCopyReferences(instruction_index);
|
||||||
|
did_something = did_something or copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var instructions_to_delete = ArrayList(u32){};
|
||||||
|
for (reachable_blocks) |basic_block_index| {
|
||||||
|
instructions_to_delete.clearRetainingCapacity();
|
||||||
|
const basic_block = builder.ir.blocks.get(basic_block_index);
|
||||||
|
for (basic_block.instructions.items, 0..) |instruction_index, index| {
|
||||||
|
const instruction = builder.ir.instructions.get(instruction_index);
|
||||||
|
switch (instruction.*) {
|
||||||
|
.copy => try instructions_to_delete.append(builder.allocator, @intCast(index)),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleted_instruction_count: usize = 0;
|
||||||
|
for (instructions_to_delete.items) |instruction_to_delete| {
|
||||||
|
_ = basic_block.instructions.orderedRemove(instruction_to_delete - deleted_instruction_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removeUnreachablePhis(builder: *Builder, reachable_blocks: []const BasicBlock.Index, instruction_index: Instruction.Index) !bool {
|
fn removeUnreachablePhis(builder: *Builder, reachable_blocks: []const BasicBlock.Index, instruction_index: Instruction.Index) !bool {
|
||||||
@ -367,7 +389,7 @@ pub const Builder = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removeCopies(builder: *Builder, instruction_index: Instruction.Index) !bool {
|
fn removeCopyReferences(builder: *Builder, instruction_index: Instruction.Index) !bool {
|
||||||
const instruction = builder.ir.instructions.get(instruction_index);
|
const instruction = builder.ir.instructions.get(instruction_index);
|
||||||
return switch (instruction.*) {
|
return switch (instruction.*) {
|
||||||
.copy => false,
|
.copy => false,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -518,37 +518,6 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyzeDeclaration(analyzer: *Analyzer, scope_index: Scope.Index, declaration: *Declaration) !Value.Index {
|
|
||||||
_ = scope_index;
|
|
||||||
_ = declaration;
|
|
||||||
_ = analyzer;
|
|
||||||
// switch (declaration.*) {
|
|
||||||
// .unresolved => |node_index| {
|
|
||||||
// const declaration_node = analyzer.nodes[node_index.unwrap()];
|
|
||||||
// return switch (declaration_node.id) {
|
|
||||||
// .simple_variable_declaration => blk: {
|
|
||||||
// const expect_type = switch (declaration_node.left.valid) {
|
|
||||||
// true => unreachable,
|
|
||||||
// false => @unionInit(ExpectType, "none", {}),
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// const initialization_expression = try analyzer.expression(scope, expect_type, declaration_node.right);
|
|
||||||
// const value = analyzer.module.values.get(initialization_expression);
|
|
||||||
// if (value.is_comptime and value.is_const) {
|
|
||||||
// break :blk initialization_expression;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// unreachable;
|
|
||||||
// },
|
|
||||||
// else => |t| @panic(@tagName(t)),
|
|
||||||
// };
|
|
||||||
// },
|
|
||||||
// .struct_type => unreachable,
|
|
||||||
// }
|
|
||||||
|
|
||||||
@panic("TODO: analyzeDeclaration");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn structType(analyzer: *Analyzer, value: *Value, parent_scope_index: Scope.Index, index: Node.Index, file_index: File.Index) !Type.Index {
|
fn structType(analyzer: *Analyzer, value: *Value, parent_scope_index: Scope.Index, index: Node.Index, file_index: File.Index) !Type.Index {
|
||||||
var node_buffer: [2]Node.Index = undefined;
|
var node_buffer: [2]Node.Index = undefined;
|
||||||
// We have the file because this might be the first file
|
// We have the file because this might be the first file
|
||||||
@ -892,7 +861,23 @@ pub fn initialize(compilation: *Compilation, module: *Module, package: *Package,
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return analyzeExistingPackage(value_allocation.ptr, compilation, module, package);
|
const result = analyzeExistingPackage(value_allocation.ptr, compilation, module, package);
|
||||||
|
|
||||||
|
var decl_iterator = module.declarations.iterator();
|
||||||
|
while (decl_iterator.nextPointer()) |decl| {
|
||||||
|
if (equal(u8, decl.name, "_start")) {
|
||||||
|
const value = module.values.get(decl.init_value);
|
||||||
|
module.entry_point = switch (value.*) {
|
||||||
|
.function => |function_index| function_index.uniqueInteger(),
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@panic("Entry point not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyzeExistingPackage(value: *Value, compilation: *Compilation, module: *Module, package: *Package) !Type.Index {
|
pub fn analyzeExistingPackage(value: *Value, compilation: *Compilation, module: *Module, package: *Package) !Type.Index {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user