instruction encoding

This commit is contained in:
David Gonzalez Martin 2023-10-01 21:04:59 -06:00
parent c7bcfa1de9
commit d391898b95
5 changed files with 629 additions and 543 deletions

View File

@ -303,6 +303,7 @@ pub const Module = struct {
calls: BlockList(Call) = .{},
argument_list: BlockList(ArgumentList) = .{},
returns: BlockList(Return) = .{},
entry_point: ?u32 = null,
pub const Descriptor = struct {
main_package_path: []const u8,

View File

@ -27,7 +27,7 @@ pub const Result = struct {
},
entry_point: u32 = 0,
fn create() !Result {
pub fn create() !Result {
return Result{
.sections = .{
.text = .{ .content = try mmap(page_size, .{ .executable = true }) },
@ -82,14 +82,6 @@ pub const Result = struct {
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 {
comptime {
assert(@typeInfo(FunctionType) == .Fn);
@ -127,79 +119,13 @@ pub fn get(comptime arch: std.Target.Cpu.Arch) type {
.x86_64 => @import("x86_64.zig"),
else => @compileError("Architecture not supported"),
};
const Instruction = backend.Instruction;
_ = Instruction;
return struct {
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);
try mir.allocateRegisters(allocator, intermediate);
// var function_iterator = intermediate.functions.iterator();
// 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 result = try mir.encode(intermediate);
const text_section = result.sections.text.content[0..result.sections.text.index];
for (text_section) |byte| {

View File

@ -25,6 +25,7 @@ pub const Result = struct {
syscalls: BlockList(Syscall) = .{},
values: BlockList(Value) = .{},
stack_references: BlockList(StackReference) = .{},
entry_point: u32 = 0,
};
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,
};
builder.ir.entry_point = module.entry_point orelse unreachable;
while (function_iterator.next()) |sema_function| {
const function_index = try builder.buildFunction(sema_function);
try builder.optimizeFunction(function_index);
@ -284,10 +287,29 @@ pub const Builder = struct {
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.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 {
@ -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);
return switch (instruction.*) {
.copy => false,

File diff suppressed because it is too large Load Diff

View File

@ -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 {
var node_buffer: [2]Node.Index = undefined;
// 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 {