mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 23:05:24 +00:00
self-hosted: restore ZIR functionality
This commit is contained in:
parent
b1b7708cc8
commit
14aa08fcd3
@ -1060,21 +1060,24 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
|
||||
.unreferenced => false,
|
||||
};
|
||||
|
||||
const type_changed = self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => return error.AnalysisFail,
|
||||
else => {
|
||||
try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
|
||||
self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
|
||||
self.allocator,
|
||||
decl.src(),
|
||||
"unable to analyze: {}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
decl.analysis = .sema_failure_retryable;
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
};
|
||||
const type_changed = if (self.root_scope.cast(Scope.ZIRModule)) |zir_module|
|
||||
try self.analyzeZirDecl(decl, zir_module.contents.module.decls[decl.src_index])
|
||||
else
|
||||
self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => return error.AnalysisFail,
|
||||
else => {
|
||||
try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
|
||||
self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
|
||||
self.allocator,
|
||||
decl.src(),
|
||||
"unable to analyze: {}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
decl.analysis = .sema_failure_retryable;
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
};
|
||||
|
||||
if (subsequent_analysis) {
|
||||
// We may need to chase the dependants and re-analyze them.
|
||||
@ -1724,71 +1727,63 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
|
||||
}
|
||||
|
||||
fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
|
||||
switch (root_scope.status) {
|
||||
.never_loaded => {
|
||||
const src_module = try self.getSrcModule(root_scope);
|
||||
// We may be analyzing it for the first time, or this may be
|
||||
// an incremental update. This code handles both cases.
|
||||
const src_module = try self.getSrcModule(root_scope);
|
||||
|
||||
// Here we ensure enough queue capacity to store all the decls, so that later we can use
|
||||
// appendAssumeCapacity.
|
||||
try self.work_queue.ensureUnusedCapacity(src_module.decls.len);
|
||||
try self.work_queue.ensureUnusedCapacity(src_module.decls.len);
|
||||
try root_scope.decls.ensureCapacity(self.allocator, src_module.decls.len);
|
||||
|
||||
for (src_module.decls) |src_decl| {
|
||||
if (src_decl.inst.cast(zir.Inst.Export)) |export_inst| {
|
||||
_ = try self.resolveDecl(&root_scope.base, src_decl);
|
||||
}
|
||||
var exports_to_resolve = std.ArrayList(*zir.Decl).init(self.allocator);
|
||||
defer exports_to_resolve.deinit();
|
||||
|
||||
// Keep track of the decls that we expect to see in this file so that
|
||||
// we know which ones have been deleted.
|
||||
var deleted_decls = std.AutoHashMap(*Decl, void).init(self.allocator);
|
||||
defer deleted_decls.deinit();
|
||||
try deleted_decls.ensureCapacity(self.decl_table.size);
|
||||
{
|
||||
var it = self.decl_table.iterator();
|
||||
while (it.next()) |kv| {
|
||||
deleted_decls.putAssumeCapacityNoClobber(kv.value, {});
|
||||
}
|
||||
}
|
||||
|
||||
for (src_module.decls) |src_decl, decl_i| {
|
||||
const name_hash = root_scope.fullyQualifiedNameHash(src_decl.name);
|
||||
if (self.decl_table.get(name_hash)) |kv| {
|
||||
const decl = kv.value;
|
||||
deleted_decls.removeAssertDiscard(decl);
|
||||
//std.debug.warn("'{}' contents: '{}'\n", .{ src_decl.name, src_decl.contents });
|
||||
if (!srcHashEql(src_decl.contents_hash, decl.contents_hash)) {
|
||||
try self.markOutdatedDecl(decl);
|
||||
decl.contents_hash = src_decl.contents_hash;
|
||||
}
|
||||
},
|
||||
|
||||
.unloaded_parse_failure,
|
||||
.unloaded_sema_failure,
|
||||
.unloaded_success,
|
||||
.loaded_sema_failure,
|
||||
.loaded_success,
|
||||
=> {
|
||||
const src_module = try self.getSrcModule(root_scope);
|
||||
|
||||
var exports_to_resolve = std.ArrayList(*zir.Decl).init(self.allocator);
|
||||
defer exports_to_resolve.deinit();
|
||||
|
||||
// Keep track of the decls that we expect to see in this file so that
|
||||
// we know which ones have been deleted.
|
||||
var deleted_decls = std.AutoHashMap(*Decl, void).init(self.allocator);
|
||||
defer deleted_decls.deinit();
|
||||
try deleted_decls.ensureCapacity(self.decl_table.size);
|
||||
{
|
||||
var it = self.decl_table.iterator();
|
||||
while (it.next()) |kv| {
|
||||
deleted_decls.putAssumeCapacityNoClobber(kv.value, {});
|
||||
}
|
||||
} else {
|
||||
const new_decl = try self.createNewDecl(
|
||||
&root_scope.base,
|
||||
src_decl.name,
|
||||
decl_i,
|
||||
name_hash,
|
||||
src_decl.contents_hash,
|
||||
);
|
||||
root_scope.decls.appendAssumeCapacity(new_decl);
|
||||
if (src_decl.inst.cast(zir.Inst.Export)) |export_inst| {
|
||||
try exports_to_resolve.append(src_decl);
|
||||
}
|
||||
|
||||
for (src_module.decls) |src_decl| {
|
||||
const name_hash = root_scope.fullyQualifiedNameHash(src_decl.name);
|
||||
if (self.decl_table.get(name_hash)) |kv| {
|
||||
const decl = kv.value;
|
||||
deleted_decls.removeAssertDiscard(decl);
|
||||
//std.debug.warn("'{}' contents: '{}'\n", .{ src_decl.name, src_decl.contents });
|
||||
if (!srcHashEql(src_decl.contents_hash, decl.contents_hash)) {
|
||||
try self.markOutdatedDecl(decl);
|
||||
decl.contents_hash = src_decl.contents_hash;
|
||||
}
|
||||
} else if (src_decl.inst.cast(zir.Inst.Export)) |export_inst| {
|
||||
try exports_to_resolve.append(src_decl);
|
||||
}
|
||||
}
|
||||
{
|
||||
// Handle explicitly deleted decls from the source code. Not to be confused
|
||||
// with when we delete decls because they are no longer referenced.
|
||||
var it = deleted_decls.iterator();
|
||||
while (it.next()) |kv| {
|
||||
//std.debug.warn("noticed '{}' deleted from source\n", .{kv.key.name});
|
||||
try self.deleteDecl(kv.key);
|
||||
}
|
||||
}
|
||||
for (exports_to_resolve.items) |export_decl| {
|
||||
_ = try self.resolveDecl(&root_scope.base, export_decl);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
{
|
||||
// Handle explicitly deleted decls from the source code. Not to be confused
|
||||
// with when we delete decls because they are no longer referenced.
|
||||
var it = deleted_decls.iterator();
|
||||
while (it.next()) |kv| {
|
||||
//std.debug.warn("noticed '{}' deleted from source\n", .{kv.key.name});
|
||||
try self.deleteDecl(kv.key);
|
||||
}
|
||||
}
|
||||
for (exports_to_resolve.items) |export_decl| {
|
||||
_ = try self.resolveZirDecl(&root_scope.base, export_decl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1933,73 +1928,67 @@ fn createNewDecl(
|
||||
return new_decl;
|
||||
}
|
||||
|
||||
fn analyzeNewDecl(self: *Module, new_decl: *Decl, src_decl: *zir.Decl) InnerError!void {
|
||||
fn analyzeZirDecl(self: *Module, decl: *Decl, src_decl: *zir.Decl) InnerError!bool {
|
||||
var decl_scope: Scope.DeclAnalysis = .{
|
||||
.decl = new_decl,
|
||||
.decl = decl,
|
||||
.arena = std.heap.ArenaAllocator.init(self.allocator),
|
||||
};
|
||||
errdefer decl_scope.arena.deinit();
|
||||
|
||||
new_decl.analysis = .in_progress;
|
||||
decl.analysis = .in_progress;
|
||||
|
||||
const typed_value = self.analyzeConstInst(&decl_scope.base, src_decl.inst) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
switch (new_decl.analysis) {
|
||||
.in_progress => new_decl.analysis = .dependency_failure,
|
||||
else => {},
|
||||
}
|
||||
new_decl.generation = self.generation;
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
};
|
||||
const typed_value = try self.analyzeConstInst(&decl_scope.base, src_decl.inst);
|
||||
const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
|
||||
|
||||
arena_state.* = decl_scope.arena.state;
|
||||
var prev_type_has_bits = false;
|
||||
var type_changed = true;
|
||||
|
||||
new_decl.typed_value = .{
|
||||
if (decl.typedValueManaged()) |tvm| {
|
||||
prev_type_has_bits = tvm.typed_value.ty.hasCodeGenBits();
|
||||
type_changed = !tvm.typed_value.ty.eql(typed_value.ty);
|
||||
|
||||
tvm.deinit(self.allocator);
|
||||
}
|
||||
|
||||
arena_state.* = decl_scope.arena.state;
|
||||
decl.typed_value = .{
|
||||
.most_recent = .{
|
||||
.typed_value = typed_value,
|
||||
.arena = arena_state,
|
||||
},
|
||||
};
|
||||
new_decl.analysis = .complete;
|
||||
new_decl.generation = self.generation;
|
||||
decl.analysis = .complete;
|
||||
decl.generation = self.generation;
|
||||
if (typed_value.ty.hasCodeGenBits()) {
|
||||
// We don't fully codegen the decl until later, but we do need to reserve a global
|
||||
// offset table index for it. This allows us to codegen decls out of dependency order,
|
||||
// increasing how many computations can be done in parallel.
|
||||
try self.bin_file.allocateDeclIndexes(new_decl);
|
||||
try self.work_queue.writeItem(.{ .codegen_decl = new_decl });
|
||||
try self.bin_file.allocateDeclIndexes(decl);
|
||||
try self.work_queue.writeItem(.{ .codegen_decl = decl });
|
||||
} else if (prev_type_has_bits) {
|
||||
self.bin_file.freeDecl(decl);
|
||||
}
|
||||
|
||||
return type_changed;
|
||||
}
|
||||
|
||||
fn resolveDecl(self: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
|
||||
// If the name is empty, then we make this an anonymous Decl.
|
||||
const scope_decl = scope.decl().?;
|
||||
const new_decl = try self.allocateNewDecl(scope, scope_decl.src_index, src_decl.contents_hash);
|
||||
try self.analyzeNewDecl(new_decl, src_decl);
|
||||
return new_decl;
|
||||
//const name_hash = Decl.hashSimpleName(src_decl.name);
|
||||
//if (self.decl_table.get(name_hash)) |kv| {
|
||||
// const decl = kv.value;
|
||||
// decl.src = src_decl.src;
|
||||
// try self.reAnalyzeDecl(decl, src_decl);
|
||||
// return decl;
|
||||
//} else if (src_decl.cast(zir.Inst.DeclVal)) |decl_val| {
|
||||
// // This is just a named reference to another decl.
|
||||
// return self.analyzeDeclVal(scope, decl_val);
|
||||
//} else {
|
||||
// const new_decl = try self.createNewDecl(scope, src_decl.name, src_decl.src, name_hash, src_decl.contents_hash);
|
||||
// try self.analyzeNewDecl(new_decl, src_decl);
|
||||
fn resolveZirDecl(self: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
|
||||
const zir_module = self.root_scope.cast(Scope.ZIRModule).?;
|
||||
const entry = zir_module.contents.module.findDecl(src_decl.name).?;
|
||||
return self.resolveZirDeclHavingIndex(scope, src_decl, entry.index);
|
||||
}
|
||||
|
||||
// return new_decl;
|
||||
//}
|
||||
fn resolveZirDeclHavingIndex(self: *Module, scope: *Scope, src_decl: *zir.Decl, src_index: usize) InnerError!*Decl {
|
||||
const name_hash = scope.namespace().fullyQualifiedNameHash(src_decl.name);
|
||||
const decl = self.decl_table.getValue(name_hash).?;
|
||||
decl.src_index = src_index;
|
||||
try self.ensureDeclAnalyzed(decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
/// Declares a dependency on the decl.
|
||||
fn resolveCompleteDecl(self: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
|
||||
const decl = try self.resolveDecl(scope, src_decl);
|
||||
fn resolveCompleteZirDecl(self: *Module, scope: *Scope, src_decl: *zir.Decl) InnerError!*Decl {
|
||||
const decl = try self.resolveZirDecl(scope, src_decl);
|
||||
switch (decl.analysis) {
|
||||
.unreferenced => unreachable,
|
||||
.in_progress => unreachable,
|
||||
@ -2014,15 +2003,32 @@ fn resolveCompleteDecl(self: *Module, scope: *Scope, src_decl: *zir.Decl) InnerE
|
||||
|
||||
.complete => {},
|
||||
}
|
||||
if (scope.decl()) |scope_decl| {
|
||||
try self.declareDeclDependency(scope_decl, decl);
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
/// TODO look into removing this function
|
||||
/// TODO Look into removing this function. The body is only needed for .zir files, not .zig files.
|
||||
fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {
|
||||
return old_inst.analyzed_inst;
|
||||
if (old_inst.analyzed_inst) |inst| return inst;
|
||||
|
||||
// If this assert trips, the instruction that was referenced did not get properly
|
||||
// analyzed before it was referenced.
|
||||
const zir_module = scope.namespace().cast(Scope.ZIRModule).?;
|
||||
const entry = if (old_inst.cast(zir.Inst.DeclVal)) |declval| blk: {
|
||||
const decl_name = declval.positionals.name;
|
||||
const entry = zir_module.contents.module.findDecl(decl_name) orelse
|
||||
return self.fail(scope, old_inst.src, "decl '{}' not found", .{decl_name});
|
||||
break :blk entry;
|
||||
} else blk: {
|
||||
// If this assert trips, the instruction that was referenced did not get
|
||||
// properly analyzed by a previous instruction analysis before it was
|
||||
// referenced by the current one.
|
||||
break :blk zir_module.contents.module.findInstDecl(old_inst).?;
|
||||
};
|
||||
const decl = try self.resolveCompleteZirDecl(scope, entry.decl);
|
||||
const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);
|
||||
const result = try self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
|
||||
old_inst.analyzed_inst = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
|
||||
@ -2071,6 +2077,7 @@ fn resolveType(self: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
|
||||
}
|
||||
|
||||
fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const u8, exported_decl: *Decl) !void {
|
||||
try self.ensureDeclAnalyzed(exported_decl);
|
||||
const typed_value = exported_decl.typed_value.most_recent.typed_value;
|
||||
switch (typed_value.ty.zigTypeTag()) {
|
||||
.Fn => {},
|
||||
@ -2439,7 +2446,7 @@ fn analyzeDeclVal(self: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerEr
|
||||
const src_decl = zir_module.contents.module.findDecl(decl_name) orelse
|
||||
return self.fail(scope, inst.base.src, "use of undeclared identifier '{}'", .{decl_name});
|
||||
|
||||
const decl = try self.resolveCompleteDecl(scope, src_decl.decl);
|
||||
const decl = try self.resolveCompleteZirDecl(scope, src_decl.decl);
|
||||
|
||||
return decl;
|
||||
}
|
||||
@ -2555,19 +2562,31 @@ fn analyzeInstCall(self: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerErro
|
||||
}
|
||||
|
||||
fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
|
||||
return self.fail(scope, fn_inst.base.src, "TODO implement ZIR fn inst", .{});
|
||||
//const fn_type = try self.resolveType(scope, fn_inst.positionals.fn_type);
|
||||
//const new_func = try scope.arena().create(Fn);
|
||||
//new_func.* = .{
|
||||
// .analysis = .{ .queued = fn_inst },
|
||||
// .owner_decl = scope.decl().?,
|
||||
//};
|
||||
//const fn_payload = try scope.arena().create(Value.Payload.Function);
|
||||
//fn_payload.* = .{ .func = new_func };
|
||||
//return self.constInst(scope, fn_inst.base.src, .{
|
||||
// .ty = fn_type,
|
||||
// .val = Value.initPayload(&fn_payload.base),
|
||||
//});
|
||||
const fn_type = try self.resolveType(scope, fn_inst.positionals.fn_type);
|
||||
const fn_zir = blk: {
|
||||
var fn_arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
errdefer fn_arena.deinit();
|
||||
|
||||
const fn_zir = try scope.arena().create(Fn.ZIR);
|
||||
fn_zir.* = .{
|
||||
.body = .{
|
||||
.instructions = fn_inst.positionals.body.instructions,
|
||||
},
|
||||
.arena = fn_arena.state,
|
||||
};
|
||||
break :blk fn_zir;
|
||||
};
|
||||
const new_func = try scope.arena().create(Fn);
|
||||
new_func.* = .{
|
||||
.analysis = .{ .queued = fn_zir },
|
||||
.owner_decl = scope.decl().?,
|
||||
};
|
||||
const fn_payload = try scope.arena().create(Value.Payload.Function);
|
||||
fn_payload.* = .{ .func = new_func };
|
||||
return self.constInst(scope, fn_inst.base.src, .{
|
||||
.ty = fn_type,
|
||||
.val = Value.initPayload(&fn_payload.base),
|
||||
});
|
||||
}
|
||||
|
||||
fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
|
||||
@ -3277,6 +3296,7 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err
|
||||
.decl => {
|
||||
const decl = scope.cast(Scope.DeclAnalysis).?.decl;
|
||||
decl.analysis = .sema_failure;
|
||||
decl.generation = self.generation;
|
||||
self.failed_decls.putAssumeCapacityNoClobber(decl, err_msg);
|
||||
},
|
||||
.block => {
|
||||
@ -3285,12 +3305,14 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err
|
||||
func.analysis = .sema_failure;
|
||||
} else {
|
||||
block.decl.analysis = .sema_failure;
|
||||
block.decl.generation = self.generation;
|
||||
}
|
||||
self.failed_decls.putAssumeCapacityNoClobber(block.decl, err_msg);
|
||||
},
|
||||
.gen_zir => {
|
||||
const gen_zir = scope.cast(Scope.GenZIR).?;
|
||||
gen_zir.decl.analysis = .sema_failure;
|
||||
gen_zir.decl.generation = self.generation;
|
||||
self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
|
||||
},
|
||||
.zir_module => {
|
||||
|
||||
@ -504,7 +504,7 @@ fn updateModule(gpa: *Allocator, module: *Module, zir_out_path: ?[]const u8) !vo
|
||||
});
|
||||
}
|
||||
} else {
|
||||
std.debug.print("Update completed in {} ms\n", .{update_nanos / std.time.ns_per_ms});
|
||||
std.log.info(.compiler, "Update completed in {} ms\n", .{update_nanos / std.time.ns_per_ms});
|
||||
}
|
||||
|
||||
if (zir_out_path) |zop| {
|
||||
|
||||
@ -30,7 +30,7 @@ pub const Inst = struct {
|
||||
/// Byte offset into the source.
|
||||
src: usize,
|
||||
/// Pre-allocated field for mapping ZIR text instructions to post-analysis instructions.
|
||||
analyzed_inst: *ir.Inst = undefined,
|
||||
analyzed_inst: ?*ir.Inst = null,
|
||||
|
||||
/// These names are used directly as the instruction names in the text format.
|
||||
pub const Tag = enum {
|
||||
@ -545,6 +545,18 @@ pub const Module = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn findInstDecl(self: Module, inst: *Inst) ?DeclAndIndex {
|
||||
for (self.decls) |decl, i| {
|
||||
if (decl.inst == inst) {
|
||||
return DeclAndIndex{
|
||||
.decl = decl,
|
||||
.index = i,
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// The allocator is used for temporary storage, but this function always returns
|
||||
/// with no resources allocated.
|
||||
pub fn writeToStream(self: Module, allocator: *Allocator, stream: var) !void {
|
||||
|
||||
@ -228,17 +228,6 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\@2 = int(2)
|
||||
\\@3 = int(3)
|
||||
\\
|
||||
\\@syscall_array = str("syscall")
|
||||
\\@sysoutreg_array = str("={rax}")
|
||||
\\@rax_array = str("{rax}")
|
||||
\\@rdi_array = str("{rdi}")
|
||||
\\@rcx_array = str("rcx")
|
||||
\\@r11_array = str("r11")
|
||||
\\@rdx_array = str("{rdx}")
|
||||
\\@rsi_array = str("{rsi}")
|
||||
\\@memory_array = str("memory")
|
||||
\\@len_array = str("len")
|
||||
\\
|
||||
\\@msg = str("Hello, world!\n")
|
||||
\\
|
||||
\\@start_fnty = fntype([], @noreturn, cc=Naked)
|
||||
@ -246,24 +235,23 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\ %SYS_exit_group = int(231)
|
||||
\\ %exit_code = as(@usize, @0)
|
||||
\\
|
||||
\\ %syscall = ref(@syscall_array)
|
||||
\\ %sysoutreg = ref(@sysoutreg_array)
|
||||
\\ %rax = ref(@rax_array)
|
||||
\\ %rdi = ref(@rdi_array)
|
||||
\\ %rcx = ref(@rcx_array)
|
||||
\\ %rdx = ref(@rdx_array)
|
||||
\\ %rsi = ref(@rsi_array)
|
||||
\\ %r11 = ref(@r11_array)
|
||||
\\ %memory = ref(@memory_array)
|
||||
\\ %syscall = str("syscall")
|
||||
\\ %sysoutreg = str("={rax}")
|
||||
\\ %rax = str("{rax}")
|
||||
\\ %rdi = str("{rdi}")
|
||||
\\ %rcx = str("rcx")
|
||||
\\ %rdx = str("{rdx}")
|
||||
\\ %rsi = str("{rsi}")
|
||||
\\ %r11 = str("r11")
|
||||
\\ %memory = str("memory")
|
||||
\\
|
||||
\\ %SYS_write = as(@usize, @1)
|
||||
\\ %STDOUT_FILENO = as(@usize, @1)
|
||||
\\
|
||||
\\ %msg_ptr = ref(@msg)
|
||||
\\ %msg_addr = ptrtoint(%msg_ptr)
|
||||
\\ %msg_addr = ptrtoint(@msg)
|
||||
\\
|
||||
\\ %len_name = ref(@len_array)
|
||||
\\ %msg_len_ptr = fieldptr(%msg_ptr, %len_name)
|
||||
\\ %len_name = str("len")
|
||||
\\ %msg_len_ptr = fieldptr(@msg, %len_name)
|
||||
\\ %msg_len = deref(%msg_len_ptr)
|
||||
\\ %rc_write = asm(%syscall, @usize,
|
||||
\\ volatile=1,
|
||||
@ -283,8 +271,7 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\});
|
||||
\\
|
||||
\\@9 = str("_start")
|
||||
\\@10 = ref(@9)
|
||||
\\@11 = export(@10, @start)
|
||||
\\@11 = export(@9, "start")
|
||||
,
|
||||
\\@noreturn = primitive(noreturn)
|
||||
\\@void = primitive(void)
|
||||
@ -294,17 +281,6 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\@2 = int(2)
|
||||
\\@3 = int(3)
|
||||
\\
|
||||
\\@syscall_array = str("syscall")
|
||||
\\@sysoutreg_array = str("={rax}")
|
||||
\\@rax_array = str("{rax}")
|
||||
\\@rdi_array = str("{rdi}")
|
||||
\\@rcx_array = str("rcx")
|
||||
\\@r11_array = str("r11")
|
||||
\\@rdx_array = str("{rdx}")
|
||||
\\@rsi_array = str("{rsi}")
|
||||
\\@memory_array = str("memory")
|
||||
\\@len_array = str("len")
|
||||
\\
|
||||
\\@msg = str("Hello, world!\n")
|
||||
\\@msg2 = str("HELL WORLD\n")
|
||||
\\
|
||||
@ -313,24 +289,23 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\ %SYS_exit_group = int(231)
|
||||
\\ %exit_code = as(@usize, @0)
|
||||
\\
|
||||
\\ %syscall = ref(@syscall_array)
|
||||
\\ %sysoutreg = ref(@sysoutreg_array)
|
||||
\\ %rax = ref(@rax_array)
|
||||
\\ %rdi = ref(@rdi_array)
|
||||
\\ %rcx = ref(@rcx_array)
|
||||
\\ %rdx = ref(@rdx_array)
|
||||
\\ %rsi = ref(@rsi_array)
|
||||
\\ %r11 = ref(@r11_array)
|
||||
\\ %memory = ref(@memory_array)
|
||||
\\ %syscall = str("syscall")
|
||||
\\ %sysoutreg = str("={rax}")
|
||||
\\ %rax = str("{rax}")
|
||||
\\ %rdi = str("{rdi}")
|
||||
\\ %rcx = str("rcx")
|
||||
\\ %rdx = str("{rdx}")
|
||||
\\ %rsi = str("{rsi}")
|
||||
\\ %r11 = str("r11")
|
||||
\\ %memory = str("memory")
|
||||
\\
|
||||
\\ %SYS_write = as(@usize, @1)
|
||||
\\ %STDOUT_FILENO = as(@usize, @1)
|
||||
\\
|
||||
\\ %msg_ptr = ref(@msg2)
|
||||
\\ %msg_addr = ptrtoint(%msg_ptr)
|
||||
\\ %msg_addr = ptrtoint(@msg2)
|
||||
\\
|
||||
\\ %len_name = ref(@len_array)
|
||||
\\ %msg_len_ptr = fieldptr(%msg_ptr, %len_name)
|
||||
\\ %len_name = str("len")
|
||||
\\ %msg_len_ptr = fieldptr(@msg2, %len_name)
|
||||
\\ %msg_len = deref(%msg_len_ptr)
|
||||
\\ %rc_write = asm(%syscall, @usize,
|
||||
\\ volatile=1,
|
||||
@ -350,8 +325,7 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\});
|
||||
\\
|
||||
\\@9 = str("_start")
|
||||
\\@10 = ref(@9)
|
||||
\\@11 = export(@10, @start)
|
||||
\\@11 = export(@9, "start")
|
||||
,
|
||||
\\@noreturn = primitive(noreturn)
|
||||
\\@void = primitive(void)
|
||||
@ -361,17 +335,6 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\@2 = int(2)
|
||||
\\@3 = int(3)
|
||||
\\
|
||||
\\@syscall_array = str("syscall")
|
||||
\\@sysoutreg_array = str("={rax}")
|
||||
\\@rax_array = str("{rax}")
|
||||
\\@rdi_array = str("{rdi}")
|
||||
\\@rcx_array = str("rcx")
|
||||
\\@r11_array = str("r11")
|
||||
\\@rdx_array = str("{rdx}")
|
||||
\\@rsi_array = str("{rsi}")
|
||||
\\@memory_array = str("memory")
|
||||
\\@len_array = str("len")
|
||||
\\
|
||||
\\@msg = str("Hello, world!\n")
|
||||
\\@msg2 = str("Editing the same msg2 decl but this time with a much longer message which will\ncause the data to need to be relocated in virtual address space.\n")
|
||||
\\
|
||||
@ -380,24 +343,23 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\ %SYS_exit_group = int(231)
|
||||
\\ %exit_code = as(@usize, @0)
|
||||
\\
|
||||
\\ %syscall = ref(@syscall_array)
|
||||
\\ %sysoutreg = ref(@sysoutreg_array)
|
||||
\\ %rax = ref(@rax_array)
|
||||
\\ %rdi = ref(@rdi_array)
|
||||
\\ %rcx = ref(@rcx_array)
|
||||
\\ %rdx = ref(@rdx_array)
|
||||
\\ %rsi = ref(@rsi_array)
|
||||
\\ %r11 = ref(@r11_array)
|
||||
\\ %memory = ref(@memory_array)
|
||||
\\ %syscall = str("syscall")
|
||||
\\ %sysoutreg = str("={rax}")
|
||||
\\ %rax = str("{rax}")
|
||||
\\ %rdi = str("{rdi}")
|
||||
\\ %rcx = str("rcx")
|
||||
\\ %rdx = str("{rdx}")
|
||||
\\ %rsi = str("{rsi}")
|
||||
\\ %r11 = str("r11")
|
||||
\\ %memory = str("memory")
|
||||
\\
|
||||
\\ %SYS_write = as(@usize, @1)
|
||||
\\ %STDOUT_FILENO = as(@usize, @1)
|
||||
\\
|
||||
\\ %msg_ptr = ref(@msg2)
|
||||
\\ %msg_addr = ptrtoint(%msg_ptr)
|
||||
\\ %msg_addr = ptrtoint(@msg2)
|
||||
\\
|
||||
\\ %len_name = ref(@len_array)
|
||||
\\ %msg_len_ptr = fieldptr(%msg_ptr, %len_name)
|
||||
\\ %len_name = str("len")
|
||||
\\ %msg_len_ptr = fieldptr(@msg2, %len_name)
|
||||
\\ %msg_len = deref(%msg_len_ptr)
|
||||
\\ %rc_write = asm(%syscall, @usize,
|
||||
\\ volatile=1,
|
||||
@ -417,8 +379,7 @@ pub fn addCases(ctx: *TestContext) void {
|
||||
\\});
|
||||
\\
|
||||
\\@9 = str("_start")
|
||||
\\@10 = ref(@9)
|
||||
\\@11 = export(@10, @start)
|
||||
\\@11 = export(@9, "start")
|
||||
},
|
||||
&[_][]const u8{
|
||||
\\Hello, world!
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user