Commit 99961f22dc

Andrew Kelley <andrew@ziglang.org>
2021-09-29 09:13:21
stage2: enable building compiler_rt when using LLVM backend
* AstGen: fix emitting `store_to_inferred_ptr` when it should be emitting `store` for a variable that has an explicit alignment. * Compilation: fix a couple memory leaks * Sema: implement support for locals that have specified alignment. * Sema: implement `@intCast` when it needs to emit an AIR instruction. * Sema: implement `@alignOf` * Implement debug printing for extended alloc ZIR instructions.
1 parent 33e77f1
src/link/Elf.zig
@@ -1284,7 +1284,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
     const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
     const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: {
         // TODO: remove when stage2 can build compiler_rt.zig
-        if (!build_options.is_stage1 or !self.base.options.use_stage1) break :blk null;
+        if (!self.base.options.use_llvm) break :blk null;
 
         // In the case of build-obj we include the compiler-rt symbols directly alongside
         // the symbols of the root source file, in the same compilation unit.
src/AstGen.zig
@@ -2567,7 +2567,11 @@ fn varDecl(
             for (init_scope.instructions.items) |src_inst| {
                 if (zir_tags[src_inst] == .store_to_block_ptr) {
                     if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
-                        zir_tags[src_inst] = .store_to_inferred_ptr;
+                        if (var_decl.ast.type_node != 0) {
+                            zir_tags[src_inst] = .store;
+                        } else {
+                            zir_tags[src_inst] = .store_to_inferred_ptr;
+                        }
                     }
                 }
                 parent_zir.appendAssumeCapacity(src_inst);
src/Compilation.zig
@@ -1574,10 +1574,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         // also test the use case of `build-obj -fcompiler-rt` with the self-hosted compiler
         // and make sure the compiler-rt symbols are emitted. Currently this is hooked up for
         // stage1 but not stage2.
-        const capable_of_building_compiler_rt = comp.bin_file.options.use_stage1;
-        const capable_of_building_ssp = comp.bin_file.options.use_stage1;
+        const capable_of_building_compiler_rt = comp.bin_file.options.use_stage1 or
+            comp.bin_file.options.use_llvm;
         const capable_of_building_zig_libc = comp.bin_file.options.use_stage1 or
             comp.bin_file.options.use_llvm;
+        const capable_of_building_ssp = comp.bin_file.options.use_stage1;
 
         if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
             if (is_exe_or_dyn_lib) {
@@ -1648,6 +1649,9 @@ pub fn destroy(self: *Compilation) void {
     if (self.compiler_rt_static_lib) |*crt_file| {
         crt_file.deinit(gpa);
     }
+    if (self.compiler_rt_obj) |*crt_file| {
+        crt_file.deinit(gpa);
+    }
     if (self.libssp_static_lib) |*crt_file| {
         crt_file.deinit(gpa);
     }
@@ -3977,6 +3981,7 @@ fn buildOutputFromZig(
         },
         .root_src_path = src_basename,
     };
+    defer main_pkg.deinitTable(comp.gpa);
     const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
     const target = comp.getTarget();
     const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{
src/Package.zig
@@ -99,15 +99,18 @@ pub fn destroy(pkg: *Package, gpa: *Allocator) void {
         }
     }
 
-    {
-        var it = pkg.table.keyIterator();
-        while (it.next()) |key| {
-            gpa.free(key.*);
-        }
+    pkg.deinitTable(gpa);
+    gpa.destroy(pkg);
+}
+
+/// Only frees memory associated with the table.
+pub fn deinitTable(pkg: *Package, gpa: *Allocator) void {
+    var it = pkg.table.keyIterator();
+    while (it.next()) |key| {
+        gpa.free(key.*);
     }
 
     pkg.table.deinit(gpa);
-    gpa.destroy(pkg);
 }
 
 pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void {
src/print_zir.zig
@@ -393,6 +393,7 @@ const Writer = struct {
             .@"asm" => try self.writeAsm(stream, extended),
             .func => try self.writeFuncExtended(stream, extended),
             .variable => try self.writeVarExtended(stream, extended),
+            .alloc => try self.writeAllocExtended(stream, extended),
 
             .compile_log,
             .typeof_peer,
@@ -423,7 +424,6 @@ const Writer = struct {
                 try stream.writeByte(')');
             },
 
-            .alloc,
             .builtin_extern,
             .wasm_memory_size,
             .wasm_memory_grow,
@@ -1767,6 +1767,30 @@ const Writer = struct {
         try stream.writeAll("))");
     }
 
+    fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
+        const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
+        const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small);
+        const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
+
+        var extra_index: usize = extra.end;
+        const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: {
+            const type_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
+            extra_index += 1;
+            break :blk type_inst;
+        };
+        const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
+            const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
+            extra_index += 1;
+            break :blk align_inst;
+        };
+        try self.writeFlag(stream, ",is_const", small.is_const);
+        try self.writeFlag(stream, ",is_comptime", small.is_comptime);
+        try self.writeOptionalInstRef(stream, ",ty=", type_inst);
+        try self.writeOptionalInstRef(stream, ",align=", align_inst);
+        try stream.writeAll(")) ");
+        try self.writeSrc(stream, src);
+    }
+
     fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
         const inst_data = self.code.instructions.items(.data)[inst].bool_br;
         const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
src/Sema.zig
@@ -1587,7 +1587,42 @@ fn zirAllocExtended(
 ) CompileError!Air.Inst.Ref {
     const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
     const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
-    return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended", .{});
+    const ty_src = src; // TODO better source location
+    const align_src = src; // TODO better source location
+    const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small);
+
+    var extra_index: usize = extra.end;
+
+    const var_ty: Type = if (small.has_type) blk: {
+        const type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
+        extra_index += 1;
+        break :blk try sema.resolveType(block, ty_src, type_ref);
+    } else {
+        return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended inferred", .{});
+    };
+
+    const alignment: u16 = if (small.has_align) blk: {
+        const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
+        extra_index += 1;
+        const alignment = try sema.resolveAlign(block, align_src, align_ref);
+        break :blk alignment;
+    } else 0;
+
+    if (small.is_comptime) {
+        return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended comptime", .{});
+    }
+
+    if (!small.is_const) {
+        return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended var", .{});
+    }
+
+    const ptr_type = try Type.ptr(sema.arena, .{
+        .pointee_type = var_ty,
+        .@"align" = alignment,
+        .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+    });
+    try sema.requireRuntimeBlock(block, src);
+    return block.addTy(.alloc, ptr_type);
 }
 
 fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -4620,7 +4655,8 @@ fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
         return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_int'", .{});
     }
 
-    return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten int", .{});
+    try sema.requireRuntimeBlock(block, operand_src);
+    return block.addTyOp(.intcast, dest_type, operand);
 }
 
 fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -8257,8 +8293,11 @@ fn zirFrameAddress(
 
 fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const inst_data = sema.code.instructions.items(.data)[inst].un_node;
-    const src = inst_data.src();
-    return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignOf", .{});
+    const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+    const ty = try sema.resolveType(block, operand_src, inst_data.operand);
+    const target = sema.mod.getTarget();
+    const abi_align = ty.abiAlignment(target);
+    return sema.addIntUnsigned(Type.comptime_int, abi_align);
 }
 
 fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/type.zig
@@ -3866,6 +3866,7 @@ pub const Type = extern union {
     };
 
     pub const @"bool" = initTag(.bool);
+    pub const @"comptime_int" = initTag(.comptime_int);
 
     pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {
         assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);
src/Zir.zig
@@ -2878,6 +2878,14 @@ pub const Inst = struct {
     /// 1. align_inst: Ref, // if small 0b00X0 is set
     pub const AllocExtended = struct {
         src_node: i32,
+
+        pub const Small = packed struct {
+            has_type: bool,
+            has_align: bool,
+            is_const: bool,
+            is_comptime: bool,
+            _: u12 = undefined,
+        };
     };
 
     pub const Export = struct {