authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-19 13:56:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-19 13:56:06-04:00
loged137d25ef0fb94f2ea0db4f993a0adfcaf63b58
tree089289335a3e6374c88ccb54c5879806132503a6
parent1cde0edff469fbe5ee62cb10a44161b4c9910f98
parent8d3cca7fc2e7b34486cc56951bb0dadb75e498a0

Merge branch 'stage2-fn-calls'


4 files changed, 77 insertions(+), 10 deletions(-)

src-self-hosted/Module.zig+8-9
......@@ -231,6 +231,7 @@ pub const Fn = struct {
231231 dependency_failure,
232232 success: Body,
233233 },
234 owner_decl: *Decl,
234235
235236 /// This memory is temporary and points to stack memory for the duration
236237 /// of Fn analysis.
......@@ -883,14 +884,6 @@ fn resolveDecl(
883884 };
884885 const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
885886
886 const has_codegen_bits = typed_value.ty.hasCodeGenBits();
887 if (has_codegen_bits) {
888 // We don't fully codegen the decl until later, but we do need to reserve a global
889 // offset table index for it. This allows us to codegen decls out of dependency order,
890 // increasing how many computations can be done in parallel.
891 try self.bin_file.allocateDeclIndexes(new_decl);
892 }
893
894887 arena_state.* = decl_scope.arena.state;
895888
896889 new_decl.typed_value = .{
......@@ -900,7 +893,12 @@ fn resolveDecl(
900893 },
901894 };
902895 new_decl.analysis = .complete;
903 if (has_codegen_bits) {
896 if (typed_value.ty.hasCodeGenBits()) {
897 // We don't fully codegen the decl until later, but we do need to reserve a global
898 // offset table index for it. This allows us to codegen decls out of dependency order,
899 // increasing how many computations can be done in parallel.
900 try self.bin_file.allocateDeclIndexes(new_decl);
901
904902 // We ensureCapacity when scanning for decls.
905903 self.work_queue.writeItemAssumeCapacity(.{ .codegen_decl = new_decl });
906904 }
......@@ -1329,6 +1327,7 @@ fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError
13291327 new_func.* = .{
13301328 .fn_type = fn_type,
13311329 .analysis = .{ .queued = fn_inst },
1330 .owner_decl = scope.decl(),
13321331 };
13331332 const fn_payload = try scope.arena().create(Value.Payload.Function);
13341333 fn_payload.* = .{ .func = new_func };
src-self-hosted/codegen.zig+14-1
......@@ -203,7 +203,20 @@ const Function = struct {
203203
204204 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
205205 const func = func_val.func;
206 return self.fail(inst.base.src, "TODO implement calling function", .{});
206 const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
207 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
208 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
209 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);
210 // ff 14 25 xx xx xx xx call [addr]
211 try self.code.resize(self.code.items.len + 7);
212 self.code.items[self.code.items.len - 7 ..][0..3].* = [3]u8{ 0xff, 0x14, 0x25 };
213 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], got_addr);
214 const return_type = func.fn_type.fnReturnType();
215 switch (return_type.zigTypeTag()) {
216 .Void => return MCValue{ .none = {} },
217 .NoReturn => return MCValue{ .unreach = {} },
218 else => return self.fail(inst.base.src, "TODO implement fn call with non-void return value", .{}),
219 }
207220 } else {
208221 return self.fail(inst.base.src, "TODO implement calling weird function values", .{});
209222 }
src-self-hosted/link.zig+2
......@@ -740,6 +740,7 @@ pub const ElfFile = struct {
740740 const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, text_size);
741741 if (amt != text_size) return error.InputOutput;
742742 shdr.sh_offset = new_offset;
743 phdr.p_offset = new_offset;
743744 }
744745 // Now that we know the code size, we need to update the program header for executable code
745746 shdr.sh_size = needed_size;
......@@ -1034,6 +1035,7 @@ pub const ElfFile = struct {
10341035 const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size);
10351036 if (amt != shdr.sh_size) return error.InputOutput;
10361037 shdr.sh_offset = new_offset;
1038 phdr.p_offset = new_offset;
10371039 }
10381040 shdr.sh_size = needed_size;
10391041 phdr.p_memsz = needed_size;
test/stage2/zir.zig+53
......@@ -209,4 +209,57 @@ pub fn addCases(ctx: *TestContext) void {
209209 \\
210210 },
211211 );
212
213 ctx.addZIRCompareOutput(
214 "function call with no args no return value",
215 &[_][]const u8{
216 \\@noreturn = primitive(noreturn)
217 \\@void = primitive(void)
218 \\@usize = primitive(usize)
219 \\@0 = int(0)
220 \\@1 = int(1)
221 \\@2 = int(2)
222 \\@3 = int(3)
223 \\
224 \\@syscall_array = str("syscall")
225 \\@sysoutreg_array = str("={rax}")
226 \\@rax_array = str("{rax}")
227 \\@rdi_array = str("{rdi}")
228 \\@rcx_array = str("rcx")
229 \\@r11_array = str("r11")
230 \\@memory_array = str("memory")
231 \\
232 \\@exit0_fnty = fntype([], @noreturn)
233 \\@exit0 = fn(@exit0_fnty, {
234 \\ %SYS_exit_group = int(231)
235 \\ %exit_code = as(@usize, @0)
236 \\
237 \\ %syscall = ref(@syscall_array)
238 \\ %sysoutreg = ref(@sysoutreg_array)
239 \\ %rax = ref(@rax_array)
240 \\ %rdi = ref(@rdi_array)
241 \\ %rcx = ref(@rcx_array)
242 \\ %r11 = ref(@r11_array)
243 \\ %memory = ref(@memory_array)
244 \\
245 \\ %rc = asm(%syscall, @usize,
246 \\ volatile=1,
247 \\ output=%sysoutreg,
248 \\ inputs=[%rax, %rdi],
249 \\ clobbers=[%rcx, %r11, %memory],
250 \\ args=[%SYS_exit_group, %exit_code])
251 \\
252 \\ %99 = unreachable()
253 \\});
254 \\
255 \\@start_fnty = fntype([], @noreturn, cc=Naked)
256 \\@start = fn(@start_fnty, {
257 \\ %0 = call(@exit0, [])
258 \\})
259 \\@9 = str("_start")
260 \\@10 = ref(@9)
261 \\@11 = export(@10, @start)
262 },
263 &[_][]const u8{""},
264 );
212265}