From 04cafd81377b9c57006a28407b0d97bc1164345e Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Wed, 25 Aug 2021 20:37:40 +0200 Subject: stage2 ARM: Add qadd, qsub, qdadd, qdsub instructions These are integer saturating arithmetic instructions --- src/codegen/arm.zig | 119 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 85 insertions(+), 34 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/arm.zig b/src/codegen/arm.zig index d30479e1f1..3743afd50f 100644 --- a/src/codegen/arm.zig +++ b/src/codegen/arm.zig @@ -192,7 +192,7 @@ pub const c_abi_int_return_regs = [_]Register{ .r0, .r1 }; /// Represents an instruction in the ARM instruction set architecture pub const Instruction = union(enum) { - DataProcessing: packed struct { + data_processing: packed struct { // Note to self: The order of the fields top-to-bottom is // right-to-left in the actual 32-bit int representation op2: u12, @@ -204,7 +204,7 @@ pub const Instruction = union(enum) { fixed: u2 = 0b00, cond: u4, }, - Multiply: packed struct { + multiply: packed struct { rn: u4, fixed_1: u4 = 0b1001, rm: u4, @@ -215,7 +215,7 @@ pub const Instruction = union(enum) { fixed_2: u6 = 0b000000, cond: u4, }, - MultiplyLong: packed struct { + multiply_long: packed struct { rn: u4, fixed_1: u4 = 0b1001, rm: u4, @@ -227,7 +227,17 @@ pub const Instruction = union(enum) { fixed_2: u5 = 0b00001, cond: u4, }, - SingleDataTransfer: packed struct { + integer_saturating_arithmetic: packed struct { + rm: u4, + fixed_1: u8 = 0b0000_0101, + rd: u4, + rn: u4, + fixed_2: u1 = 0b0, + opc: u2, + fixed_3: u5 = 0b00010, + cond: u4, + }, + single_data_transfer: packed struct { offset: u12, rd: u4, rn: u4, @@ -240,7 +250,7 @@ pub const Instruction = union(enum) { fixed: u2 = 0b01, cond: u4, }, - ExtraLoadStore: packed struct { + extra_load_store: packed struct { imm4l: u4, fixed_1: u1 = 0b1, op2: u2, @@ -256,7 +266,7 @@ pub const Instruction = union(enum) { fixed_3: u3 = 0b000, cond: u4, }, - BlockDataTransfer: packed struct { + block_data_transfer: packed struct { register_list: u16, rn: u4, load_store: u1, @@ -267,25 +277,25 @@ pub const Instruction = union(enum) { fixed: u3 = 0b100, cond: u4, }, - Branch: packed struct { + branch: packed struct { offset: u24, link: u1, fixed: u3 = 0b101, cond: u4, }, - BranchExchange: packed struct { + branch_exchange: packed struct { rn: u4, fixed_1: u1 = 0b1, link: u1, fixed_2: u22 = 0b0001_0010_1111_1111_1111_00, cond: u4, }, - SupervisorCall: packed struct { + supervisor_call: packed struct { comment: u24, fixed: u4 = 0b1111, cond: u4, }, - Breakpoint: packed struct { + breakpoint: packed struct { imm4: u4, fixed_1: u4 = 0b0111, imm12: u12, @@ -293,7 +303,7 @@ pub const Instruction = union(enum) { }, /// Represents the possible operations which can be performed by a - /// DataProcessing instruction + /// Data Processing instruction const Opcode = enum(u4) { // Rd := Op1 AND Op2 @"and", @@ -530,16 +540,17 @@ pub const Instruction = union(enum) { pub fn toU32(self: Instruction) u32 { return switch (self) { - .DataProcessing => |v| @bitCast(u32, v), - .Multiply => |v| @bitCast(u32, v), - .MultiplyLong => |v| @bitCast(u32, v), - .SingleDataTransfer => |v| @bitCast(u32, v), - .ExtraLoadStore => |v| @bitCast(u32, v), - .BlockDataTransfer => |v| @bitCast(u32, v), - .Branch => |v| @bitCast(u32, v), - .BranchExchange => |v| @bitCast(u32, v), - .SupervisorCall => |v| @bitCast(u32, v), - .Breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20), + .data_processing => |v| @bitCast(u32, v), + .multiply => |v| @bitCast(u32, v), + .multiply_long => |v| @bitCast(u32, v), + .integer_saturating_arithmetic => |v| @bitCast(u32, v), + .single_data_transfer => |v| @bitCast(u32, v), + .extra_load_store => |v| @bitCast(u32, v), + .block_data_transfer => |v| @bitCast(u32, v), + .branch => |v| @bitCast(u32, v), + .branch_exchange => |v| @bitCast(u32, v), + .supervisor_call => |v| @bitCast(u32, v), + .breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20), }; } @@ -554,7 +565,7 @@ pub const Instruction = union(enum) { op2: Operand, ) Instruction { return Instruction{ - .DataProcessing = .{ + .data_processing = .{ .cond = @enumToInt(cond), .i = @boolToInt(op2 == .Immediate), .opcode = @enumToInt(opcode), @@ -573,7 +584,7 @@ pub const Instruction = union(enum) { top: bool, ) Instruction { return Instruction{ - .DataProcessing = .{ + .data_processing = .{ .cond = @enumToInt(cond), .i = 1, .opcode = if (top) 0b1010 else 0b1000, @@ -594,7 +605,7 @@ pub const Instruction = union(enum) { ra: ?Register, ) Instruction { return Instruction{ - .Multiply = .{ + .multiply = .{ .cond = @enumToInt(cond), .accumulate = @boolToInt(ra != null), .set_cond = set_cond, @@ -617,7 +628,7 @@ pub const Instruction = union(enum) { rn: Register, ) Instruction { return Instruction{ - .MultiplyLong = .{ + .multiply_long = .{ .cond = @enumToInt(cond), .unsigned = signed, .accumulate = accumulate, @@ -630,6 +641,24 @@ pub const Instruction = union(enum) { }; } + fn integerSaturationArithmetic( + cond: Condition, + rd: Register, + rm: Register, + rn: Register, + opc: u2, + ) Instruction { + return Instruction{ + .integer_saturating_arithmetic = .{ + .rm = rm.id(), + .rd = rd.id(), + .rn = rn.id(), + .opc = opc, + .cond = @enumToInt(cond), + }, + }; + } + fn singleDataTransfer( cond: Condition, rd: Register, @@ -642,7 +671,7 @@ pub const Instruction = union(enum) { load_store: u1, ) Instruction { return Instruction{ - .SingleDataTransfer = .{ + .single_data_transfer = .{ .cond = @enumToInt(cond), .rn = rn.id(), .rd = rd.id(), @@ -678,7 +707,7 @@ pub const Instruction = union(enum) { }; return Instruction{ - .ExtraLoadStore = .{ + .extra_load_store = .{ .imm4l = imm4l, .op2 = op2, .imm4h = imm4h, @@ -705,7 +734,7 @@ pub const Instruction = union(enum) { load_store: u1, ) Instruction { return Instruction{ - .BlockDataTransfer = .{ + .block_data_transfer = .{ .register_list = @bitCast(u16, reg_list), .rn = rn.id(), .load_store = load_store, @@ -720,7 +749,7 @@ pub const Instruction = union(enum) { fn branch(cond: Condition, offset: i26, link: u1) Instruction { return Instruction{ - .Branch = .{ + .branch = .{ .cond = @enumToInt(cond), .link = link, .offset = @bitCast(u24, @intCast(i24, offset >> 2)), @@ -730,7 +759,7 @@ pub const Instruction = union(enum) { fn branchExchange(cond: Condition, rn: Register, link: u1) Instruction { return Instruction{ - .BranchExchange = .{ + .branch_exchange = .{ .cond = @enumToInt(cond), .link = link, .rn = rn.id(), @@ -740,7 +769,7 @@ pub const Instruction = union(enum) { fn supervisorCall(cond: Condition, comment: u24) Instruction { return Instruction{ - .SupervisorCall = .{ + .supervisor_call = .{ .cond = @enumToInt(cond), .comment = comment, }, @@ -749,7 +778,7 @@ pub const Instruction = union(enum) { fn breakpoint(imm: u16) Instruction { return Instruction{ - .Breakpoint = .{ + .breakpoint = .{ .imm12 = @truncate(u12, imm >> 4), .imm4 = @truncate(u4, imm), }, @@ -873,6 +902,24 @@ pub const Instruction = union(enum) { return dataProcessing(cond, .mvn, 1, rd, .r0, op2); } + // Integer Saturating Arithmetic + + pub fn qadd(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction { + return integerSaturationArithmetic(cond, rd, rm, rn, 0b00); + } + + pub fn qsub(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction { + return integerSaturationArithmetic(cond, rd, rm, rn, 0b01); + } + + pub fn qdadd(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction { + return integerSaturationArithmetic(cond, rd, rm, rn, 0b10); + } + + pub fn qdsub(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction { + return integerSaturationArithmetic(cond, rd, rm, rn, 0b11); + } + // movw and movt pub fn movw(cond: Condition, rd: Register, imm: u16) Instruction { @@ -887,7 +934,7 @@ pub const Instruction = union(enum) { pub fn mrs(cond: Condition, rd: Register, psr: Psr) Instruction { return Instruction{ - .DataProcessing = .{ + .data_processing = .{ .cond = @enumToInt(cond), .i = 0, .opcode = if (psr == .spsr) 0b1010 else 0b1000, @@ -901,7 +948,7 @@ pub const Instruction = union(enum) { pub fn msr(cond: Condition, psr: Psr, op: Operand) Instruction { return Instruction{ - .DataProcessing = .{ + .data_processing = .{ .cond = @enumToInt(cond), .i = 0, .opcode = if (psr == .spsr) 0b1011 else 0b1001, @@ -1294,6 +1341,10 @@ test "serialize instructions" { .inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }), .expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100, }, + .{ // qadd r0, r7, r8 + .inst = Instruction.qadd(.al, .r0, .r7, .r8), + .expected = 0b1110_00010_00_0_1000_0000_0000_0101_0111, + }, }; for (testcases) |case| { -- cgit v1.2.3 From e878a6633f2447666217a5f9247af7c34507dca0 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Mon, 30 Aug 2021 00:31:40 -0700 Subject: stage2: implement runtime `%` and `@rem` --- src/Air.zig | 5 +++++ src/Liveness.zig | 1 + src/Sema.zig | 14 +++++++++++--- src/codegen.zig | 9 +++++++++ src/codegen/c.zig | 1 + src/codegen/llvm.zig | 14 ++++++++++++++ src/codegen/llvm/bindings.zig | 9 +++++++++ src/print_air.zig | 1 + 8 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src/codegen') diff --git a/src/Air.zig b/src/Air.zig index 6e4125be44..60e5fdce1c 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -69,6 +69,10 @@ pub const Inst = struct { /// is the same as both operands. /// Uses the `bin_op` field. div, + /// Integer or float remainder. + /// Both operands are guaranteed to be the same type, and the result type is the same as both operands. + /// Uses the `bin_op` field. + rem, /// Add an offset to a pointer, returning a new pointer. /// The offset is in element type units, not bytes. /// Wrapping is undefined behavior. @@ -462,6 +466,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .mul, .mulwrap, .div, + .rem, .bit_and, .bit_or, .xor, diff --git a/src/Liveness.zig b/src/Liveness.zig index 6a47bfe597..2f1ecc9c43 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -231,6 +231,7 @@ fn analyzeInst( .mul, .mulwrap, .div, + .rem, .ptr_add, .ptr_sub, .bit_and, diff --git a/src/Sema.zig b/src/Sema.zig index bab7a67c28..00c9029721 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5714,6 +5714,14 @@ fn analyzeArithmetic( try sema.requireRuntimeBlock(block, lhs_src); } + if (zir_tag == .mod_rem) { + const dirty_lhs = lhs_ty.isSignedInt() or lhs_ty.isFloat(); + const dirty_rhs = rhs_ty.isSignedInt() or rhs_ty.isFloat(); + if (dirty_lhs or dirty_rhs) { + return sema.mod.fail(&block.base, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty }); + } + } + const air_tag: Air.Inst.Tag = switch (zir_tag) { .add => .add, .addwrap => .addwrap, @@ -5722,6 +5730,8 @@ fn analyzeArithmetic( .mul => .mul, .mulwrap => .mulwrap, .div => .div, + .mod_rem => .rem, + .rem => .rem, else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}'", .{@tagName(zir_tag)}), }; @@ -7184,9 +7194,7 @@ fn zirMod(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A } fn zirRem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const inst_data = sema.code.instructions.items(.data)[inst].pl_node; - const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirRem", .{}); + return sema.zirArithmetic(block, inst); } fn zirShlExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { diff --git a/src/codegen.zig b/src/codegen.zig index 9103c7ad17..a706b3b21c 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -809,6 +809,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .mul => try self.airMul(inst), .mulwrap => try self.airMulWrap(inst), .div => try self.airDiv(inst), + .rem => try self.airRem(inst), .cmp_lt => try self.airCmp(inst, .lt), .cmp_lte => try self.airCmp(inst, .lte), @@ -1266,6 +1267,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } + fn airRem(self: *Self, inst: Air.Inst.Index) !void { + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { + else => return self.fail("TODO implement rem for {}", .{self.target.cpu.arch}), + }; + return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); + } + fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 2084b1e1ce..fd964f2829 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -858,6 +858,7 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM // TODO use a different strategy for div that communicates to the optimizer // that wrapping is UB. .div => try airBinOp( o, inst, " / "), + .rem => try airBinOp( o, inst, " % "), .cmp_eq => try airBinOp(o, inst, " == "), .cmp_gt => try airBinOp(o, inst, " > "), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d7aa2d45b3..5d20e380b4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -985,6 +985,7 @@ pub const FuncGen = struct { .mul => try self.airMul(inst, false), .mulwrap => try self.airMul(inst, true), .div => try self.airDiv(inst), + .rem => try self.airRem(inst), .ptr_add => try self.airPtrAdd(inst), .ptr_sub => try self.airPtrSub(inst), @@ -1727,6 +1728,19 @@ pub const FuncGen = struct { return self.builder.buildUDiv(lhs, rhs, ""); } + fn airRem(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const lhs = try self.resolveInst(bin_op.lhs); + const rhs = try self.resolveInst(bin_op.rhs); + const inst_ty = self.air.typeOfIndex(inst); + + if (inst_ty.isFloat()) return self.builder.buildFRem(lhs, rhs, ""); + if (inst_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, ""); + return self.builder.buildURem(lhs, rhs, ""); + } + fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index d33ca29d4f..3c59fbe056 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -386,6 +386,15 @@ pub const Builder = opaque { pub const buildFDiv = LLVMBuildFDiv; extern fn LLVMBuildFDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + pub const buildURem = LLVMBuildURem; + extern fn LLVMBuildURem(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + + pub const buildSRem = LLVMBuildSRem; + extern fn LLVMBuildSRem(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + + pub const buildFRem = LLVMBuildFRem; + extern fn LLVMBuildFRem(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + pub const buildAnd = LLVMBuildAnd; extern fn LLVMBuildAnd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; diff --git a/src/print_air.zig b/src/print_air.zig index 276158f720..0106d0a0f3 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -109,6 +109,7 @@ const Writer = struct { .mul, .mulwrap, .div, + .rem, .ptr_add, .ptr_sub, .bit_and, -- cgit v1.2.3 From 908f72210741cc10b6bf494ace06f8e74a08f215 Mon Sep 17 00:00:00 2001 From: Jacob G-W Date: Sun, 22 Aug 2021 14:44:33 -0400 Subject: stage2 llvm backend: if an array has a senteniel, add it --- src/codegen/llvm.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d7aa2d45b3..e487dec538 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -796,11 +796,13 @@ pub const DeclGen = struct { const gpa = self.gpa; const elem_ty = tv.ty.elemType(); const elem_vals = payload.data; - const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len); + const sento = tv.ty.sentinel(); + const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len + @boolToInt(sento != null)); defer gpa.free(llvm_elems); for (elem_vals) |elem_val, i| { llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = elem_val }); } + if (sento) |sent| llvm_elems[elem_vals.len] = try self.genTypedValue(.{ .ty = elem_ty, .val = sent }); const llvm_elem_ty = try self.llvmType(elem_ty); return llvm_elem_ty.constArray( llvm_elems.ptr, -- cgit v1.2.3 From 50c6b6cc66e8e7501f7ebf5d3846a365d1d47eb8 Mon Sep 17 00:00:00 2001 From: Meghan Date: Tue, 31 Aug 2021 10:50:09 -0700 Subject: stage2: only initialize the llvm backend for the target we are building (#9659) --- src/codegen/llvm.zig | 151 ++++++++++++++++++++++-- src/codegen/llvm/bindings.zig | 269 ++++++++++++++---------------------------- 2 files changed, 229 insertions(+), 191 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d7aa2d45b3..f176c74ec6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -167,7 +167,7 @@ pub const Object = struct { const context = llvm.Context.create(); errdefer context.dispose(); - initializeLLVMTargets(); + initializeLLVMTarget(options.target.cpu.arch); const root_nameZ = try gpa.dupeZ(u8, options.root_name); defer gpa.free(root_nameZ); @@ -256,14 +256,6 @@ pub const Object = struct { gpa.destroy(self); } - fn initializeLLVMTargets() void { - llvm.initializeAllTargets(); - llvm.initializeAllTargetInfos(); - llvm.initializeAllTargetMCs(); - llvm.initializeAllAsmPrinters(); - llvm.initializeAllAsmParsers(); - } - fn locPath( arena: *Allocator, opt_loc: ?Compilation.EmitLoc, @@ -1957,3 +1949,144 @@ pub const FuncGen = struct { return self.llvmModule().getIntrinsicDeclaration(id, null, 0); } }; + +fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { + switch (arch) { + .aarch64, .aarch64_be, .aarch64_32 => { + llvm.LLVMInitializeAArch64Target(); + llvm.LLVMInitializeAArch64TargetInfo(); + llvm.LLVMInitializeAArch64TargetMC(); + llvm.LLVMInitializeAArch64AsmPrinter(); + llvm.LLVMInitializeAArch64AsmParser(); + }, + .amdgcn => { + llvm.LLVMInitializeAMDGPUTarget(); + llvm.LLVMInitializeAMDGPUTargetInfo(); + llvm.LLVMInitializeAMDGPUTargetMC(); + llvm.LLVMInitializeAMDGPUAsmPrinter(); + llvm.LLVMInitializeAMDGPUAsmParser(); + }, + .arm, .armeb => { + llvm.LLVMInitializeARMTarget(); + llvm.LLVMInitializeARMTargetInfo(); + llvm.LLVMInitializeARMTargetMC(); + llvm.LLVMInitializeARMAsmPrinter(); + llvm.LLVMInitializeARMAsmParser(); + }, + .avr => { + llvm.LLVMInitializeAVRTarget(); + llvm.LLVMInitializeAVRTargetInfo(); + llvm.LLVMInitializeAVRTargetMC(); + llvm.LLVMInitializeAVRAsmPrinter(); + llvm.LLVMInitializeAVRAsmParser(); + }, + .bpfel, .bpfeb => { + llvm.LLVMInitializeBPFTarget(); + llvm.LLVMInitializeBPFTargetInfo(); + llvm.LLVMInitializeBPFTargetMC(); + llvm.LLVMInitializeBPFAsmPrinter(); + llvm.LLVMInitializeBPFAsmParser(); + }, + .hexagon => { + llvm.LLVMInitializeHexagonTarget(); + llvm.LLVMInitializeHexagonTargetInfo(); + llvm.LLVMInitializeHexagonTargetMC(); + llvm.LLVMInitializeHexagonAsmPrinter(); + llvm.LLVMInitializeHexagonAsmParser(); + }, + .lanai => { + llvm.LLVMInitializeLanaiTarget(); + llvm.LLVMInitializeLanaiTargetInfo(); + llvm.LLVMInitializeLanaiTargetMC(); + llvm.LLVMInitializeLanaiAsmPrinter(); + llvm.LLVMInitializeLanaiAsmParser(); + }, + .mips, .mipsel, .mips64, .mips64el => { + llvm.LLVMInitializeMipsTarget(); + llvm.LLVMInitializeMipsTargetInfo(); + llvm.LLVMInitializeMipsTargetMC(); + llvm.LLVMInitializeMipsAsmPrinter(); + llvm.LLVMInitializeMipsAsmParser(); + }, + .msp430 => { + llvm.LLVMInitializeMSP430Target(); + llvm.LLVMInitializeMSP430TargetInfo(); + llvm.LLVMInitializeMSP430TargetMC(); + llvm.LLVMInitializeMSP430AsmPrinter(); + llvm.LLVMInitializeMSP430AsmParser(); + }, + .nvptx, .nvptx64 => { + llvm.LLVMInitializeNVPTXTarget(); + llvm.LLVMInitializeNVPTXTargetInfo(); + llvm.LLVMInitializeNVPTXTargetMC(); + llvm.LLVMInitializeNVPTXAsmPrinter(); + // There is no LLVMInitializeNVPTXAsmParser function available. + }, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => { + llvm.LLVMInitializePowerPCTarget(); + llvm.LLVMInitializePowerPCTargetInfo(); + llvm.LLVMInitializePowerPCTargetMC(); + llvm.LLVMInitializePowerPCAsmPrinter(); + llvm.LLVMInitializePowerPCAsmParser(); + }, + .riscv32, .riscv64 => { + llvm.LLVMInitializeRISCVTarget(); + llvm.LLVMInitializeRISCVTargetInfo(); + llvm.LLVMInitializeRISCVTargetMC(); + llvm.LLVMInitializeRISCVAsmPrinter(); + llvm.LLVMInitializeRISCVAsmParser(); + }, + .sparc, .sparcv9, .sparcel => { + llvm.LLVMInitializeSparcTarget(); + llvm.LLVMInitializeSparcTargetInfo(); + llvm.LLVMInitializeSparcTargetMC(); + llvm.LLVMInitializeSparcAsmPrinter(); + llvm.LLVMInitializeSparcAsmParser(); + }, + .s390x => { + llvm.LLVMInitializeSystemZTarget(); + llvm.LLVMInitializeSystemZTargetInfo(); + llvm.LLVMInitializeSystemZTargetMC(); + llvm.LLVMInitializeSystemZAsmPrinter(); + llvm.LLVMInitializeSystemZAsmParser(); + }, + .wasm32, .wasm64 => { + llvm.LLVMInitializeWebAssemblyTarget(); + llvm.LLVMInitializeWebAssemblyTargetInfo(); + llvm.LLVMInitializeWebAssemblyTargetMC(); + llvm.LLVMInitializeWebAssemblyAsmPrinter(); + llvm.LLVMInitializeWebAssemblyAsmParser(); + }, + .i386, .x86_64 => { + llvm.LLVMInitializeX86Target(); + llvm.LLVMInitializeX86TargetInfo(); + llvm.LLVMInitializeX86TargetMC(); + llvm.LLVMInitializeX86AsmPrinter(); + llvm.LLVMInitializeX86AsmParser(); + }, + .xcore => { + llvm.LLVMInitializeXCoreTarget(); + llvm.LLVMInitializeXCoreTargetInfo(); + llvm.LLVMInitializeXCoreTargetMC(); + llvm.LLVMInitializeXCoreAsmPrinter(); + // There is no LLVMInitializeXCoreAsmParser function available. + }, + .arc => {}, + .csky => {}, + .r600 => {}, + .tce, .tcele => {}, + .thumb, .thumbeb => {}, + .le32, .le64 => {}, + .amdil, .amdil64 => {}, + .hsail, .hsail64 => {}, + .spir, .spir64 => {}, + .kalimba => {}, + .shave => {}, + .renderscript32 => {}, + .renderscript64 => {}, + .ve => {}, + .spu_2 => {}, + .spirv32 => {}, + .spirv64 => {}, + } +} diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index d33ca29d4f..f632b9c2ce 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -596,188 +596,93 @@ pub const Target = opaque { extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const Target, ErrorMessage: *[*:0]const u8) Bool; }; -extern fn LLVMInitializeAArch64TargetInfo() void; -extern fn LLVMInitializeAMDGPUTargetInfo() void; -extern fn LLVMInitializeARMTargetInfo() void; -extern fn LLVMInitializeAVRTargetInfo() void; -extern fn LLVMInitializeBPFTargetInfo() void; -extern fn LLVMInitializeHexagonTargetInfo() void; -extern fn LLVMInitializeLanaiTargetInfo() void; -extern fn LLVMInitializeMipsTargetInfo() void; -extern fn LLVMInitializeMSP430TargetInfo() void; -extern fn LLVMInitializeNVPTXTargetInfo() void; -extern fn LLVMInitializePowerPCTargetInfo() void; -extern fn LLVMInitializeRISCVTargetInfo() void; -extern fn LLVMInitializeSparcTargetInfo() void; -extern fn LLVMInitializeSystemZTargetInfo() void; -extern fn LLVMInitializeWebAssemblyTargetInfo() void; -extern fn LLVMInitializeX86TargetInfo() void; -extern fn LLVMInitializeXCoreTargetInfo() void; -extern fn LLVMInitializeAArch64Target() void; -extern fn LLVMInitializeAMDGPUTarget() void; -extern fn LLVMInitializeARMTarget() void; -extern fn LLVMInitializeAVRTarget() void; -extern fn LLVMInitializeBPFTarget() void; -extern fn LLVMInitializeHexagonTarget() void; -extern fn LLVMInitializeLanaiTarget() void; -extern fn LLVMInitializeMipsTarget() void; -extern fn LLVMInitializeMSP430Target() void; -extern fn LLVMInitializeNVPTXTarget() void; -extern fn LLVMInitializePowerPCTarget() void; -extern fn LLVMInitializeRISCVTarget() void; -extern fn LLVMInitializeSparcTarget() void; -extern fn LLVMInitializeSystemZTarget() void; -extern fn LLVMInitializeWebAssemblyTarget() void; -extern fn LLVMInitializeX86Target() void; -extern fn LLVMInitializeXCoreTarget() void; -extern fn LLVMInitializeAArch64TargetMC() void; -extern fn LLVMInitializeAMDGPUTargetMC() void; -extern fn LLVMInitializeARMTargetMC() void; -extern fn LLVMInitializeAVRTargetMC() void; -extern fn LLVMInitializeBPFTargetMC() void; -extern fn LLVMInitializeHexagonTargetMC() void; -extern fn LLVMInitializeLanaiTargetMC() void; -extern fn LLVMInitializeMipsTargetMC() void; -extern fn LLVMInitializeMSP430TargetMC() void; -extern fn LLVMInitializeNVPTXTargetMC() void; -extern fn LLVMInitializePowerPCTargetMC() void; -extern fn LLVMInitializeRISCVTargetMC() void; -extern fn LLVMInitializeSparcTargetMC() void; -extern fn LLVMInitializeSystemZTargetMC() void; -extern fn LLVMInitializeWebAssemblyTargetMC() void; -extern fn LLVMInitializeX86TargetMC() void; -extern fn LLVMInitializeXCoreTargetMC() void; -extern fn LLVMInitializeAArch64AsmPrinter() void; -extern fn LLVMInitializeAMDGPUAsmPrinter() void; -extern fn LLVMInitializeARMAsmPrinter() void; -extern fn LLVMInitializeAVRAsmPrinter() void; -extern fn LLVMInitializeBPFAsmPrinter() void; -extern fn LLVMInitializeHexagonAsmPrinter() void; -extern fn LLVMInitializeLanaiAsmPrinter() void; -extern fn LLVMInitializeMipsAsmPrinter() void; -extern fn LLVMInitializeMSP430AsmPrinter() void; -extern fn LLVMInitializeNVPTXAsmPrinter() void; -extern fn LLVMInitializePowerPCAsmPrinter() void; -extern fn LLVMInitializeRISCVAsmPrinter() void; -extern fn LLVMInitializeSparcAsmPrinter() void; -extern fn LLVMInitializeSystemZAsmPrinter() void; -extern fn LLVMInitializeWebAssemblyAsmPrinter() void; -extern fn LLVMInitializeX86AsmPrinter() void; -extern fn LLVMInitializeXCoreAsmPrinter() void; -extern fn LLVMInitializeAArch64AsmParser() void; -extern fn LLVMInitializeAMDGPUAsmParser() void; -extern fn LLVMInitializeARMAsmParser() void; -extern fn LLVMInitializeAVRAsmParser() void; -extern fn LLVMInitializeBPFAsmParser() void; -extern fn LLVMInitializeHexagonAsmParser() void; -extern fn LLVMInitializeLanaiAsmParser() void; -extern fn LLVMInitializeMipsAsmParser() void; -extern fn LLVMInitializeMSP430AsmParser() void; -extern fn LLVMInitializePowerPCAsmParser() void; -extern fn LLVMInitializeRISCVAsmParser() void; -extern fn LLVMInitializeSparcAsmParser() void; -extern fn LLVMInitializeSystemZAsmParser() void; -extern fn LLVMInitializeWebAssemblyAsmParser() void; -extern fn LLVMInitializeX86AsmParser() void; - -pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos; -fn LLVMInitializeAllTargetInfos() callconv(.C) void { - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAMDGPUTargetInfo(); - LLVMInitializeARMTargetInfo(); - LLVMInitializeAVRTargetInfo(); - LLVMInitializeBPFTargetInfo(); - LLVMInitializeHexagonTargetInfo(); - LLVMInitializeLanaiTargetInfo(); - LLVMInitializeMipsTargetInfo(); - LLVMInitializeMSP430TargetInfo(); - LLVMInitializeNVPTXTargetInfo(); - LLVMInitializePowerPCTargetInfo(); - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeSparcTargetInfo(); - LLVMInitializeSystemZTargetInfo(); - LLVMInitializeWebAssemblyTargetInfo(); - LLVMInitializeX86TargetInfo(); - LLVMInitializeXCoreTargetInfo(); -} -pub const initializeAllTargets = LLVMInitializeAllTargets; -fn LLVMInitializeAllTargets() callconv(.C) void { - LLVMInitializeAArch64Target(); - LLVMInitializeAMDGPUTarget(); - LLVMInitializeARMTarget(); - LLVMInitializeAVRTarget(); - LLVMInitializeBPFTarget(); - LLVMInitializeHexagonTarget(); - LLVMInitializeLanaiTarget(); - LLVMInitializeMipsTarget(); - LLVMInitializeMSP430Target(); - LLVMInitializeNVPTXTarget(); - LLVMInitializePowerPCTarget(); - LLVMInitializeRISCVTarget(); - LLVMInitializeSparcTarget(); - LLVMInitializeSystemZTarget(); - LLVMInitializeWebAssemblyTarget(); - LLVMInitializeX86Target(); - LLVMInitializeXCoreTarget(); -} -pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs; -fn LLVMInitializeAllTargetMCs() callconv(.C) void { - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAMDGPUTargetMC(); - LLVMInitializeARMTargetMC(); - LLVMInitializeAVRTargetMC(); - LLVMInitializeBPFTargetMC(); - LLVMInitializeHexagonTargetMC(); - LLVMInitializeLanaiTargetMC(); - LLVMInitializeMipsTargetMC(); - LLVMInitializeMSP430TargetMC(); - LLVMInitializeNVPTXTargetMC(); - LLVMInitializePowerPCTargetMC(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeSparcTargetMC(); - LLVMInitializeSystemZTargetMC(); - LLVMInitializeWebAssemblyTargetMC(); - LLVMInitializeX86TargetMC(); - LLVMInitializeXCoreTargetMC(); -} -pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters; -fn LLVMInitializeAllAsmPrinters() callconv(.C) void { - LLVMInitializeAArch64AsmPrinter(); - LLVMInitializeAMDGPUAsmPrinter(); - LLVMInitializeARMAsmPrinter(); - LLVMInitializeAVRAsmPrinter(); - LLVMInitializeBPFAsmPrinter(); - LLVMInitializeHexagonAsmPrinter(); - LLVMInitializeLanaiAsmPrinter(); - LLVMInitializeMipsAsmPrinter(); - LLVMInitializeMSP430AsmPrinter(); - LLVMInitializeNVPTXAsmPrinter(); - LLVMInitializePowerPCAsmPrinter(); - LLVMInitializeRISCVAsmPrinter(); - LLVMInitializeSparcAsmPrinter(); - LLVMInitializeSystemZAsmPrinter(); - LLVMInitializeWebAssemblyAsmPrinter(); - LLVMInitializeX86AsmPrinter(); - LLVMInitializeXCoreAsmPrinter(); -} -pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers; -fn LLVMInitializeAllAsmParsers() callconv(.C) void { - LLVMInitializeAArch64AsmParser(); - LLVMInitializeAMDGPUAsmParser(); - LLVMInitializeARMAsmParser(); - LLVMInitializeAVRAsmParser(); - LLVMInitializeBPFAsmParser(); - LLVMInitializeHexagonAsmParser(); - LLVMInitializeLanaiAsmParser(); - LLVMInitializeMipsAsmParser(); - LLVMInitializeMSP430AsmParser(); - LLVMInitializePowerPCAsmParser(); - LLVMInitializeRISCVAsmParser(); - LLVMInitializeSparcAsmParser(); - LLVMInitializeSystemZAsmParser(); - LLVMInitializeWebAssemblyAsmParser(); - LLVMInitializeX86AsmParser(); -} +pub extern fn LLVMInitializeAArch64TargetInfo() void; +pub extern fn LLVMInitializeAMDGPUTargetInfo() void; +pub extern fn LLVMInitializeARMTargetInfo() void; +pub extern fn LLVMInitializeAVRTargetInfo() void; +pub extern fn LLVMInitializeBPFTargetInfo() void; +pub extern fn LLVMInitializeHexagonTargetInfo() void; +pub extern fn LLVMInitializeLanaiTargetInfo() void; +pub extern fn LLVMInitializeMipsTargetInfo() void; +pub extern fn LLVMInitializeMSP430TargetInfo() void; +pub extern fn LLVMInitializeNVPTXTargetInfo() void; +pub extern fn LLVMInitializePowerPCTargetInfo() void; +pub extern fn LLVMInitializeRISCVTargetInfo() void; +pub extern fn LLVMInitializeSparcTargetInfo() void; +pub extern fn LLVMInitializeSystemZTargetInfo() void; +pub extern fn LLVMInitializeWebAssemblyTargetInfo() void; +pub extern fn LLVMInitializeX86TargetInfo() void; +pub extern fn LLVMInitializeXCoreTargetInfo() void; + +pub extern fn LLVMInitializeAArch64Target() void; +pub extern fn LLVMInitializeAMDGPUTarget() void; +pub extern fn LLVMInitializeARMTarget() void; +pub extern fn LLVMInitializeAVRTarget() void; +pub extern fn LLVMInitializeBPFTarget() void; +pub extern fn LLVMInitializeHexagonTarget() void; +pub extern fn LLVMInitializeLanaiTarget() void; +pub extern fn LLVMInitializeMipsTarget() void; +pub extern fn LLVMInitializeMSP430Target() void; +pub extern fn LLVMInitializeNVPTXTarget() void; +pub extern fn LLVMInitializePowerPCTarget() void; +pub extern fn LLVMInitializeRISCVTarget() void; +pub extern fn LLVMInitializeSparcTarget() void; +pub extern fn LLVMInitializeSystemZTarget() void; +pub extern fn LLVMInitializeWebAssemblyTarget() void; +pub extern fn LLVMInitializeX86Target() void; +pub extern fn LLVMInitializeXCoreTarget() void; + +pub extern fn LLVMInitializeAArch64TargetMC() void; +pub extern fn LLVMInitializeAMDGPUTargetMC() void; +pub extern fn LLVMInitializeARMTargetMC() void; +pub extern fn LLVMInitializeAVRTargetMC() void; +pub extern fn LLVMInitializeBPFTargetMC() void; +pub extern fn LLVMInitializeHexagonTargetMC() void; +pub extern fn LLVMInitializeLanaiTargetMC() void; +pub extern fn LLVMInitializeMipsTargetMC() void; +pub extern fn LLVMInitializeMSP430TargetMC() void; +pub extern fn LLVMInitializeNVPTXTargetMC() void; +pub extern fn LLVMInitializePowerPCTargetMC() void; +pub extern fn LLVMInitializeRISCVTargetMC() void; +pub extern fn LLVMInitializeSparcTargetMC() void; +pub extern fn LLVMInitializeSystemZTargetMC() void; +pub extern fn LLVMInitializeWebAssemblyTargetMC() void; +pub extern fn LLVMInitializeX86TargetMC() void; +pub extern fn LLVMInitializeXCoreTargetMC() void; + +pub extern fn LLVMInitializeAArch64AsmPrinter() void; +pub extern fn LLVMInitializeAMDGPUAsmPrinter() void; +pub extern fn LLVMInitializeARMAsmPrinter() void; +pub extern fn LLVMInitializeAVRAsmPrinter() void; +pub extern fn LLVMInitializeBPFAsmPrinter() void; +pub extern fn LLVMInitializeHexagonAsmPrinter() void; +pub extern fn LLVMInitializeLanaiAsmPrinter() void; +pub extern fn LLVMInitializeMipsAsmPrinter() void; +pub extern fn LLVMInitializeMSP430AsmPrinter() void; +pub extern fn LLVMInitializeNVPTXAsmPrinter() void; +pub extern fn LLVMInitializePowerPCAsmPrinter() void; +pub extern fn LLVMInitializeRISCVAsmPrinter() void; +pub extern fn LLVMInitializeSparcAsmPrinter() void; +pub extern fn LLVMInitializeSystemZAsmPrinter() void; +pub extern fn LLVMInitializeWebAssemblyAsmPrinter() void; +pub extern fn LLVMInitializeX86AsmPrinter() void; +pub extern fn LLVMInitializeXCoreAsmPrinter() void; + +pub extern fn LLVMInitializeAArch64AsmParser() void; +pub extern fn LLVMInitializeAMDGPUAsmParser() void; +pub extern fn LLVMInitializeARMAsmParser() void; +pub extern fn LLVMInitializeAVRAsmParser() void; +pub extern fn LLVMInitializeBPFAsmParser() void; +pub extern fn LLVMInitializeHexagonAsmParser() void; +pub extern fn LLVMInitializeLanaiAsmParser() void; +pub extern fn LLVMInitializeMipsAsmParser() void; +pub extern fn LLVMInitializeMSP430AsmParser() void; +pub extern fn LLVMInitializePowerPCAsmParser() void; +pub extern fn LLVMInitializeRISCVAsmParser() void; +pub extern fn LLVMInitializeSparcAsmParser() void; +pub extern fn LLVMInitializeSystemZAsmParser() void; +pub extern fn LLVMInitializeWebAssemblyAsmParser() void; +pub extern fn LLVMInitializeX86AsmParser() void; extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; -- cgit v1.2.3 From 435d8ae5367a23699e0b8d2b68b9928367252a54 Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Tue, 31 Aug 2021 09:27:30 +0200 Subject: stage2 ARM: add missing parameters for bic, bics --- src/codegen/arm.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/arm.zig b/src/codegen/arm.zig index 3743afd50f..42e3e52fac 100644 --- a/src/codegen/arm.zig +++ b/src/codegen/arm.zig @@ -886,11 +886,11 @@ pub const Instruction = union(enum) { return dataProcessing(cond, .mov, 1, rd, .r0, op2); } - pub fn bic(cond: Condition, rd: Register, op2: Operand) Instruction { + pub fn bic(cond: Condition, rd: Register, rn: Register, op2: Operand) Instruction { return dataProcessing(cond, .bic, 0, rd, rn, op2); } - pub fn bics(cond: Condition, rd: Register, op2: Operand) Instruction { + pub fn bics(cond: Condition, rd: Register, rn: Register, op2: Operand) Instruction { return dataProcessing(cond, .bic, 1, rd, rn, op2); } -- cgit v1.2.3 From 332eafeb7f3d866556ab767b960a04661bc43bc7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 28 Aug 2021 15:35:59 -0700 Subject: stage2: first pass at implementing usingnamespace Ran into a design flaw here which will need to get solved by having AstGen annotate ZIR with which instructions are closed over. --- src/AstGen.zig | 5 +- src/Module.zig | 62 ++++++++++--- src/Sema.zig | 115 ++++++++++++++++++++---- src/codegen.zig | 26 +++--- src/codegen/aarch64.zig | 2 +- src/codegen/arm.zig | 2 +- src/codegen/riscv64.zig | 4 +- src/codegen/x86.zig | 16 ++-- src/codegen/x86_64.zig | 34 +++---- src/link.zig | 2 +- src/link/Elf.zig | 152 ++++++++++++++++---------------- src/link/MachO/DebugSymbols.zig | 140 ++++++++++++++--------------- src/link/MachO/Object.zig | 4 +- test/behavior.zig | 3 +- test/behavior/eval.zig | 6 -- test/behavior/usingnamespace.zig | 23 ++--- test/behavior/usingnamespace_stage1.zig | 22 +++++ test/compile_errors.zig | 10 +++ 18 files changed, 385 insertions(+), 243 deletions(-) create mode 100644 test/behavior/usingnamespace_stage1.zig (limited to 'src/codegen') diff --git a/src/AstGen.zig b/src/AstGen.zig index 245e40c3a1..c96a97ddeb 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -6416,6 +6416,9 @@ fn identifier( }, .top => break, }; + if (found_already == null) { + return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); + } // Decl references happen by name rather than ZIR index so that when unrelated // decls are modified, ZIR code containing references to them can be unmodified. @@ -10052,7 +10055,7 @@ fn isPrimitive(name: []const u8) bool { } } -/// Local variables shadowing detection, including function parameters and primitives. +/// Local variables shadowing detection, including function parameters. fn detectLocalShadowing( astgen: *AstGen, scope: *Scope, diff --git a/src/Module.zig b/src/Module.zig index 77f880b492..c17780cdc3 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -365,6 +365,8 @@ pub const Decl = struct { /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it /// deletes the Decl on the spot. alive: bool, + /// Whether the Decl is a `usingnamespace` declaration. + is_usingnamespace: bool, /// Represents the position of the code in the output file. /// This is populated regardless of semantic analysis and code generation. @@ -1008,6 +1010,11 @@ pub const Scope = struct { anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, + /// Key is usingnamespace Decl itself. To find the namespace being included, + /// the Decl Value has to be resolved as a Type which has a Namespace. + /// Value is whether the usingnamespace decl is marked `pub`. + usingnamespace_set: std.AutoHashMapUnmanaged(*Decl, bool) = .{}, + pub fn deinit(ns: *Namespace, mod: *Module) void { ns.destroyDecls(mod); ns.* = undefined; @@ -3174,6 +3181,31 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { errdefer decl_arena.deinit(); const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); + if (decl.is_usingnamespace) { + const ty_ty = Type.initTag(.type); + if (!decl_tv.ty.eql(ty_ty)) { + return mod.fail(&block_scope.base, src, "expected type, found {}", .{decl_tv.ty}); + } + var buffer: Value.ToTypeBuffer = undefined; + const ty = decl_tv.val.toType(&buffer); + if (ty.getNamespace() == null) { + return mod.fail(&block_scope.base, src, "type {} has no namespace", .{ty}); + } + + decl.ty = ty_ty; + decl.val = try Value.Tag.ty.create(&decl_arena.allocator, ty); + decl.align_val = Value.initTag(.null_value); + decl.linksection_val = Value.initTag(.null_value); + decl.has_tv = true; + decl.owns_tv = false; + decl_arena_state.* = decl_arena.state; + decl.value_arena = decl_arena_state; + decl.analysis = .complete; + decl.generation = mod.generation; + + return true; + } + if (decl_tv.val.castTag(.function)) |fn_payload| { const func = fn_payload.data; const owns_tv = func.owner_decl == decl; @@ -3269,16 +3301,13 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { if (type_changed and mod.emit_h != null) { try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); } - } else if (decl_tv.ty.zigTypeTag() == .Type) { - // In case this Decl is a struct or union, we need to resolve the fields - // while we still have the `Sema` in scope, so that the field type expressions - // can use the resolved AIR instructions that they possibly reference. - // We do this after the decl is populated and set to `complete` so that a `Decl` - // may reference itself. - var buffer: Value.ToTypeBuffer = undefined; - const ty = decl.val.toType(&buffer); - try sema.resolveDeclFields(&block_scope, src, ty); } + // In case this Decl is a struct or union, we need to resolve the fields + // while we still have the `Sema` in scope, so that the field type expressions + // can use the resolved AIR instructions that they possibly reference. + // We do this after the decl is populated and set to `complete` so that a `Decl` + // may reference itself. + try sema.resolvePendingTypes(&block_scope); if (decl.is_exported) { const export_src = src; // TODO point to the export token @@ -3494,7 +3523,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi // zig fmt: off const is_pub = (flags & 0b0001) != 0; - const is_exported = (flags & 0b0010) != 0; + const export_bit = (flags & 0b0010) != 0; const has_align = (flags & 0b0100) != 0; const has_linksection = (flags & 0b1000) != 0; // zig fmt: on @@ -3509,7 +3538,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi var is_named_test = false; const decl_name: [:0]const u8 = switch (decl_name_index) { 0 => name: { - if (is_exported) { + if (export_bit) { const i = iter.usingnamespace_index; iter.usingnamespace_index += 1; break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i}); @@ -3535,11 +3564,17 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi } }, }; + const is_exported = export_bit and decl_name_index != 0; + const is_usingnamespace = export_bit and decl_name_index == 0; + if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); // We create a Decl for it regardless of analysis status. const gop = try namespace.decls.getOrPut(gpa, decl_name); if (!gop.found_existing) { const new_decl = try mod.allocateNewDecl(namespace, decl_node); + if (is_usingnamespace) { + namespace.usingnamespace_set.putAssumeCapacity(new_decl, is_pub); + } log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); new_decl.src_line = line; new_decl.name = decl_name; @@ -3548,7 +3583,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi // test decls if in test mode, get analyzed. const decl_pkg = namespace.file_scope.pkg; const want_analysis = is_exported or switch (decl_name_index) { - 0 => true, // comptime decl + 0 => true, // comptime or usingnamespace decl 1 => blk: { // test decl with no name. Skip the part where we check against // the test name filter. @@ -3571,6 +3606,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi } new_decl.is_pub = is_pub; new_decl.is_exported = is_exported; + new_decl.is_usingnamespace = is_usingnamespace; new_decl.has_align = has_align; new_decl.has_linksection = has_linksection; new_decl.zir_decl_index = @intCast(u32, decl_sub_index); @@ -3587,6 +3623,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi decl.is_pub = is_pub; decl.is_exported = is_exported; + decl.is_usingnamespace = is_usingnamespace; decl.has_align = has_align; decl.has_linksection = has_linksection; decl.zir_decl_index = @intCast(u32, decl_sub_index); @@ -3979,6 +4016,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast. .has_linksection = false, .has_align = false, .alive = false, + .is_usingnamespace = false, }; return new_decl; } diff --git a/src/Sema.zig b/src/Sema.zig index 108470ec79..b3eb3b1b85 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -58,6 +58,9 @@ comptime_args_fn_inst: Zir.Inst.Index = 0, /// extra hash table lookup in the `monomorphed_funcs` set. /// Sema will set this to null when it takes ownership. preallocated_new_func: ?*Module.Fn = null, +/// Collects struct, union, enum, and opaque decls which need to have their +/// fields resolved before this Sema is deinitialized. +types_pending_resolution: std.ArrayListUnmanaged(Type) = .{}, const std = @import("std"); const mem = std.mem; @@ -90,6 +93,7 @@ pub fn deinit(sema: *Sema) void { sema.air_values.deinit(gpa); sema.inst_map.deinit(gpa); sema.decl_val_table.deinit(gpa); + sema.types_pending_resolution.deinit(gpa); sema.* = undefined; } @@ -908,7 +912,9 @@ fn zirStructDecl( &struct_obj.namespace, new_decl, new_decl.name, }); try sema.analyzeStructDecl(new_decl, inst, struct_obj); + try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); try new_decl.finalizeNewArena(&new_decl_arena); + sema.types_pending_resolution.appendAssumeCapacity(struct_ty); return sema.analyzeDeclVal(block, src, new_decl); } @@ -1198,7 +1204,9 @@ fn zirUnionDecl( _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl); + try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); try new_decl.finalizeNewArena(&new_decl_arena); + sema.types_pending_resolution.appendAssumeCapacity(union_ty); return sema.analyzeDeclVal(block, src, new_decl); } @@ -2324,42 +2332,105 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr } fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl { - // TODO emit a compile error if more than one decl would be matched. var namespace = sema.namespace; while (true) { - if (try sema.lookupInNamespace(namespace, name)) |decl| { + if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl| { return decl; } namespace = namespace.parent orelse break; } - return sema.mod.fail(&block.base, src, "use of undeclared identifier '{s}'", .{name}); + unreachable; // AstGen detects use of undeclared identifier errors. } /// This looks up a member of a specific namespace. It is affected by `usingnamespace` but /// only for ones in the specified namespace. fn lookupInNamespace( sema: *Sema, + block: *Scope.Block, + src: LazySrcLoc, namespace: *Scope.Namespace, ident_name: []const u8, + observe_usingnamespace: bool, ) CompileError!?*Decl { + const mod = sema.mod; + const namespace_decl = namespace.getDecl(); if (namespace_decl.analysis == .file_failure) { - try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl); + try mod.declareDeclDependency(sema.owner_decl, namespace_decl); return error.AnalysisFail; } - // TODO implement usingnamespace - if (namespace.decls.get(ident_name)) |decl| { - try sema.mod.declareDeclDependency(sema.owner_decl, decl); + if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) { + const src_file = block.src_decl.namespace.file_scope; + + const gpa = sema.gpa; + var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Scope.Namespace, void) = .{}; + defer checked_namespaces.deinit(gpa); + + // Keep track of name conflicts for error notes. + var candidates: std.ArrayListUnmanaged(*Decl) = .{}; + defer candidates.deinit(gpa); + + try checked_namespaces.put(gpa, namespace, {}); + var check_i: usize = 0; + + while (check_i < checked_namespaces.count()) : (check_i += 1) { + const check_ns = checked_namespaces.keys()[check_i]; + if (check_ns.decls.get(ident_name)) |decl| { + // Skip decls which are not marked pub, which are in a different + // file than the `a.b`/`@hasDecl` syntax. + if (decl.is_pub or src_file == decl.namespace.file_scope) { + try candidates.append(gpa, decl); + } + } + var it = check_ns.usingnamespace_set.iterator(); + while (it.next()) |entry| { + const sub_usingnamespace_decl = entry.key_ptr.*; + const sub_is_pub = entry.value_ptr.*; + if (!sub_is_pub and src_file != sub_usingnamespace_decl.namespace.file_scope) { + // Skip usingnamespace decls which are not marked pub, which are in + // a different file than the `a.b`/`@hasDecl` syntax. + continue; + } + try sema.ensureDeclAnalyzed(sub_usingnamespace_decl); + const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; + const sub_ns = ns_ty.getNamespace().?; + try checked_namespaces.put(gpa, sub_ns, {}); + } + } + + switch (candidates.items.len) { + 0 => {}, + 1 => { + const decl = candidates.items[0]; + try mod.declareDeclDependency(sema.owner_decl, decl); + return decl; + }, + else => { + const msg = msg: { + const msg = try mod.errMsg(&block.base, src, "ambiguous reference", .{}); + errdefer msg.destroy(gpa); + for (candidates.items) |candidate| { + const src_loc = candidate.srcLoc(); + try mod.errNoteNonLazy(src_loc, msg, "declared here", .{}); + } + break :msg msg; + }; + return mod.failWithOwnedErrorMsg(&block.base, msg); + }, + } + } else if (namespace.decls.get(ident_name)) |decl| { + try mod.declareDeclDependency(sema.owner_decl, decl); return decl; } + log.debug("{*} ({s}) depends on non-existence of '{s}' in {*} ({s})", .{ sema.owner_decl, sema.owner_decl.name, ident_name, namespace_decl, namespace_decl.name, }); // TODO This dependency is too strong. Really, it should only be a dependency // on the non-existence of `ident_name` in the namespace. We can lessen the number of // outdated declarations by making this dependency more sophisticated. - try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl); + try mod.declareDeclDependency(sema.owner_decl, namespace_decl); return null; } @@ -2727,10 +2798,7 @@ fn analyzeCall( // we need to resolve the field type expressions right here, right now, while // the child `Sema` is still available, with the AIR instruction map intact, // because the field type expressions may reference into it. - if (sema.typeOf(result).zigTypeTag() == .Type) { - const ty = try sema.analyzeAsType(&child_block, call_src, result); - try sema.resolveDeclFields(&child_block, call_src, ty); - } + try sema.resolvePendingTypes(&child_block); } break :res2 result; @@ -5332,6 +5400,7 @@ fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const src = inst_data.src(); const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const container_type = try sema.resolveType(block, lhs_src, extra.lhs); @@ -5344,7 +5413,7 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr "expected struct, enum, union, or opaque, found '{}'", .{container_type}, ); - if (try sema.lookupInNamespace(namespace, decl_name)) |decl| { + if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) { return Air.Inst.Ref.bool_true; } @@ -8203,7 +8272,7 @@ fn namespaceLookup( ) CompileError!?*Decl { const mod = sema.mod; const gpa = sema.gpa; - if (try sema.lookupInNamespace(namespace, decl_name)) |decl| { + if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) { const msg = msg: { const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{ @@ -8919,8 +8988,7 @@ fn analyzeDeclVal( return result; } -fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { - try sema.mod.declareDeclDependency(sema.owner_decl, decl); +fn ensureDeclAnalyzed(sema: *Sema, decl: *Decl) CompileError!void { sema.mod.ensureDeclAnalyzed(decl) catch |err| { if (sema.owner_func) |owner_func| { owner_func.state = .dependency_failure; @@ -8929,6 +8997,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { } return err; }; +} + +fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { + try sema.mod.declareDeclDependency(sema.owner_decl, decl); + try sema.ensureDeclAnalyzed(decl); const decl_tv = try decl.typedValue(); if (decl_tv.val.castTag(.variable)) |payload| { @@ -9560,6 +9633,16 @@ pub fn resolveTypeLayout( } } +pub fn resolvePendingTypes(sema: *Sema, block: *Scope.Block) !void { + for (sema.types_pending_resolution.items) |ty| { + // If an error happens resolving the fields of a struct, it will be marked + // invalid and a proper compile error set up. But we should still look at the + // other types pending resolution. + const src: LazySrcLoc = .{ .node_offset = 0 }; + sema.resolveDeclFields(block, src, ty) catch continue; + } +} + /// `sema` and `block` are expected to be the same ones used for the `Decl`. pub fn resolveDeclFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void { switch (ty.tag()) { diff --git a/src/codegen.zig b/src/codegen.zig index cf51f30fe3..0a8797d887 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -899,7 +899,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn dbgSetPrologueEnd(self: *Self) InnerError!void { switch (self.debug_output) { .dwarf => |dbg_out| { - try dbg_out.dbg_line.append(DW.LNS_set_prologue_end); + try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); }, .none => {}, @@ -909,7 +909,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn dbgSetEpilogueBegin(self: *Self) InnerError!void { switch (self.debug_output) { .dwarf => |dbg_out| { - try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin); + try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); }, .none => {}, @@ -925,13 +925,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // It lets you emit single-byte opcodes that add different numbers to // both the PC and the line number at the same time. try dbg_out.dbg_line.ensureUnusedCapacity(11); - dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc); + dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; if (delta_line != 0) { - dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_line); + dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; } - dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_copy); + dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); }, .none => {}, } @@ -1010,7 +1010,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .dwarf => |dbg_out| { assert(ty.hasCodeGenBits()); const index = dbg_out.dbg_info.items.len; - try dbg_out.dbg_info.resize(index + 4); // DW.AT_type, DW.FORM_ref4 + try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.gpa, ty); if (!gop.found_existing) { @@ -2438,13 +2438,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .dwarf => |dbg_out| { try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3); dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); - dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc + dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc 1, // ULEB128 dwarf expression length reg.dwarfLocOp(), }); try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT_type, DW.FORM_ref4 - dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string + try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 + dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string }, .none => {}, } @@ -2467,15 +2467,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { var counting_writer = std.io.countingWriter(std.io.null_writer); leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; - // DW.AT_location, DW.FORM_exprloc + // DW.AT.location, DW.FORM.exprloc // ULEB128 dwarf expression length try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); - try dbg_out.dbg_info.append(DW.OP_breg11); + try dbg_out.dbg_info.append(DW.OP.breg11); try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT_type, DW.FORM_ref4 - dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string + try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 + dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string }, else => {}, } diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index 1c176df017..dfda04da85 100644 --- a/src/codegen/aarch64.zig +++ b/src/codegen/aarch64.zig @@ -52,7 +52,7 @@ pub const Register = enum(u6) { } pub fn dwarfLocOp(self: Register) u8 { - return @as(u8, self.id()) + DW.OP_reg0; + return @as(u8, self.id()) + DW.OP.reg0; } }; diff --git a/src/codegen/arm.zig b/src/codegen/arm.zig index 42e3e52fac..ec9152f96b 100644 --- a/src/codegen/arm.zig +++ b/src/codegen/arm.zig @@ -170,7 +170,7 @@ pub const Register = enum(u5) { } pub fn dwarfLocOp(self: Register) u8 { - return @as(u8, self.id()) + DW.OP_reg0; + return @as(u8, self.id()) + DW.OP.reg0; } }; diff --git a/src/codegen/riscv64.zig b/src/codegen/riscv64.zig index 831f74b1b7..b297737816 100644 --- a/src/codegen/riscv64.zig +++ b/src/codegen/riscv64.zig @@ -390,7 +390,7 @@ pub const RawRegister = enum(u5) { x24, x25, x26, x27, x28, x29, x30, x31, pub fn dwarfLocOp(reg: RawRegister) u8 { - return @enumToInt(reg) + DW.OP_reg0; + return @enumToInt(reg) + DW.OP.reg0; } }; @@ -424,7 +424,7 @@ pub const Register = enum(u5) { } pub fn dwarfLocOp(reg: Register) u8 { - return @as(u8, @enumToInt(reg)) + DW.OP_reg0; + return @as(u8, @enumToInt(reg)) + DW.OP.reg0; } }; diff --git a/src/codegen/x86.zig b/src/codegen/x86.zig index fdad4e56db..5b981b9ef4 100644 --- a/src/codegen/x86.zig +++ b/src/codegen/x86.zig @@ -59,14 +59,14 @@ pub const Register = enum(u8) { pub fn dwarfLocOp(reg: Register) u8 { return switch (reg.to32()) { - .eax => DW.OP_reg0, - .ecx => DW.OP_reg1, - .edx => DW.OP_reg2, - .ebx => DW.OP_reg3, - .esp => DW.OP_reg4, - .ebp => DW.OP_reg5, - .esi => DW.OP_reg6, - .edi => DW.OP_reg7, + .eax => DW.OP.reg0, + .ecx => DW.OP.reg1, + .edx => DW.OP.reg2, + .ebx => DW.OP.reg3, + .esp => DW.OP.reg4, + .ebp => DW.OP.reg5, + .esi => DW.OP.reg6, + .edi => DW.OP.reg7, else => unreachable, }; } diff --git a/src/codegen/x86_64.zig b/src/codegen/x86_64.zig index 2964d7245e..72a7468041 100644 --- a/src/codegen/x86_64.zig +++ b/src/codegen/x86_64.zig @@ -115,23 +115,23 @@ pub const Register = enum(u8) { pub fn dwarfLocOp(self: Register) u8 { return switch (self.to64()) { - .rax => DW.OP_reg0, - .rdx => DW.OP_reg1, - .rcx => DW.OP_reg2, - .rbx => DW.OP_reg3, - .rsi => DW.OP_reg4, - .rdi => DW.OP_reg5, - .rbp => DW.OP_reg6, - .rsp => DW.OP_reg7, - - .r8 => DW.OP_reg8, - .r9 => DW.OP_reg9, - .r10 => DW.OP_reg10, - .r11 => DW.OP_reg11, - .r12 => DW.OP_reg12, - .r13 => DW.OP_reg13, - .r14 => DW.OP_reg14, - .r15 => DW.OP_reg15, + .rax => DW.OP.reg0, + .rdx => DW.OP.reg1, + .rcx => DW.OP.reg2, + .rbx => DW.OP.reg3, + .rsi => DW.OP.reg4, + .rdi => DW.OP.reg5, + .rbp => DW.OP.reg6, + .rsp => DW.OP.reg7, + + .r8 => DW.OP.reg8, + .r9 => DW.OP.reg9, + .r10 => DW.OP.reg10, + .r11 => DW.OP.reg11, + .r12 => DW.OP.reg12, + .r13 => DW.OP.reg13, + .r14 => DW.OP.reg14, + .r15 => DW.OP.reg15, else => unreachable, }; diff --git a/src/link.zig b/src/link.zig index 1293fab4d2..dbca4fc956 100644 --- a/src/link.zig +++ b/src/link.zig @@ -179,7 +179,7 @@ pub const File = struct { /// This is where the .debug_info tag for the type is. off: u32, /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). - /// List of DW.AT_type / DW.FORM_ref4 that points to the type. + /// List of DW.AT.type / DW.FORM.ref4 that points to the type. relocs: std.ArrayListUnmanaged(u32), }; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 9ddebd3453..938fede8ab 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -772,48 +772,48 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { // These are LEB encoded but since the values are all less than 127 // we can simply append these bytes. const abbrev_buf = [_]u8{ - abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header - DW.AT_stmt_list, DW.FORM_sec_offset, DW.AT_low_pc, - DW.FORM_addr, DW.AT_high_pc, DW.FORM_addr, - DW.AT_name, DW.FORM_strp, DW.AT_comp_dir, - DW.FORM_strp, DW.AT_producer, DW.FORM_strp, - DW.AT_language, DW.FORM_data2, 0, + abbrev_compile_unit, DW.TAG.compile_unit, DW.CHILDREN.yes, // header + DW.AT.stmt_list, DW.FORM.sec_offset, DW.AT.low_pc, + DW.FORM.addr, DW.AT.high_pc, DW.FORM.addr, + DW.AT.name, DW.FORM.strp, DW.AT.comp_dir, + DW.FORM.strp, DW.AT.producer, DW.FORM.strp, + DW.AT.language, DW.FORM.data2, 0, 0, // table sentinel abbrev_subprogram, - DW.TAG_subprogram, - DW.CHILDREN_yes, // header - DW.AT_low_pc, - DW.FORM_addr, - DW.AT_high_pc, - DW.FORM_data4, - DW.AT_type, - DW.FORM_ref4, - DW.AT_name, - DW.FORM_string, + DW.TAG.subprogram, + DW.CHILDREN.yes, // header + DW.AT.low_pc, + DW.FORM.addr, + DW.AT.high_pc, + DW.FORM.data4, + DW.AT.type, + DW.FORM.ref4, + DW.AT.name, + DW.FORM.string, 0, 0, // table sentinel abbrev_subprogram_retvoid, - DW.TAG_subprogram, DW.CHILDREN_yes, // header - DW.AT_low_pc, DW.FORM_addr, - DW.AT_high_pc, DW.FORM_data4, - DW.AT_name, DW.FORM_string, + DW.TAG.subprogram, DW.CHILDREN.yes, // header + DW.AT.low_pc, DW.FORM.addr, + DW.AT.high_pc, DW.FORM.data4, + DW.AT.name, DW.FORM.string, 0, 0, // table sentinel abbrev_base_type, - DW.TAG_base_type, - DW.CHILDREN_no, // header - DW.AT_encoding, - DW.FORM_data1, - DW.AT_byte_size, - DW.FORM_data1, - DW.AT_name, - DW.FORM_string, 0, 0, // table sentinel - abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header + DW.TAG.base_type, + DW.CHILDREN.no, // header + DW.AT.encoding, + DW.FORM.data1, + DW.AT.byte_size, + DW.FORM.data1, + DW.AT.name, + DW.FORM.string, 0, 0, // table sentinel + abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header 0, 0, // table sentinel abbrev_parameter, - DW.TAG_formal_parameter, DW.CHILDREN_no, // header - DW.AT_location, DW.FORM_exprloc, - DW.AT_type, DW.FORM_ref4, - DW.AT_name, DW.FORM_string, + DW.TAG.formal_parameter, DW.CHILDREN.no, // header + DW.AT.location, DW.FORM.exprloc, + DW.AT.type, DW.FORM.ref4, + DW.AT.name, DW.FORM.string, 0, 0, // table sentinel 0, @@ -897,7 +897,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; di_buf.appendAssumeCapacity(abbrev_compile_unit); - self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT_stmt_list, DW.FORM_sec_offset + self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset self.writeDwarfAddrAssumeCapacity(&di_buf, low_pc); self.writeDwarfAddrAssumeCapacity(&di_buf, high_pc); self.writeDwarfAddrAssumeCapacity(&di_buf, name_strp); @@ -906,7 +906,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: // http://dwarfstd.org/ShowIssue.php?issue=171115.1 // Until then we say it is C99. - mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99, target_endian); + mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG.C99, target_endian); if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { // Move the first N decls to the end to make more padding for the header. @@ -1030,7 +1030,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { di_buf.items.len += ptr_width_bytes; // We will come back and write this. const after_header_len = di_buf.items.len; - const opcode_base = DW.LNS_set_isa + 1; + const opcode_base = DW.LNS.set_isa + 1; di_buf.appendSliceAssumeCapacity(&[_]u8{ 1, // minimum_instruction_length 1, // maximum_operations_per_instruction @@ -1041,18 +1041,18 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { // Standard opcode lengths. The number of items here is based on `opcode_base`. // The value is the number of LEB128 operands the instruction takes. - 0, // `DW.LNS_copy` - 1, // `DW.LNS_advance_pc` - 1, // `DW.LNS_advance_line` - 1, // `DW.LNS_set_file` - 1, // `DW.LNS_set_column` - 0, // `DW.LNS_negate_stmt` - 0, // `DW.LNS_set_basic_block` - 0, // `DW.LNS_const_add_pc` - 1, // `DW.LNS_fixed_advance_pc` - 0, // `DW.LNS_set_prologue_end` - 0, // `DW.LNS_set_epilogue_begin` - 1, // `DW.LNS_set_isa` + 0, // `DW.LNS.copy` + 1, // `DW.LNS.advance_pc` + 1, // `DW.LNS.advance_line` + 1, // `DW.LNS.set_file` + 1, // `DW.LNS.set_column` + 0, // `DW.LNS.negate_stmt` + 0, // `DW.LNS.set_basic_block` + 0, // `DW.LNS.const_add_pc` + 1, // `DW.LNS.fixed_advance_pc` + 0, // `DW.LNS.set_prologue_end` + 0, // `DW.LNS.set_epilogue_begin` + 1, // `DW.LNS.set_isa` 0, // include_directories (none except the compilation unit cwd) }); // file_names[0] @@ -2053,7 +2053,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address // range of the compilation unit. When we expand the text section, this range changes, - // so the DW_TAG_compile_unit tag of the .debug_info section becomes dirty. + // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. self.debug_info_header_dirty = true; // This becomes dirty for the same reason. We could potentially make this more // fine-grained with the addition of support for more compilation units. It is planned to @@ -2303,22 +2303,22 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven const ptr_width_bytes = self.ptrWidthBytes(); dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ - DW.LNS_extended_op, + DW.LNS.extended_op, ptr_width_bytes + 1, - DW.LNE_set_address, + DW.LNE.set_address, }); // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); dbg_line_buffer.items.len += ptr_width_bytes; - dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.advance_line); // This is the "relocatable" relative line offset from the previous function's end curly // to this function's begin curly. assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len); // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); - dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_file); assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); // Once we support more than one source file, this will have the ability to be more // than one possible value. @@ -2327,7 +2327,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven // Emit a line for the begin curly with prologue_end=false. The codegen will // do the work of setting prologue_end=true and epilogue_begin=true. - dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); // .debug_info subprogram const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1]; @@ -2344,9 +2344,9 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven // "relocations" and have to be in this fixed place so that functions can be // moved in virtual address space. assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); - dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT_low_pc, DW.FORM_addr + dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); - dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 + dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 if (fn_ret_has_bits) { const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, fn_ret_type); if (!gop.found_existing) { @@ -2356,9 +2356,9 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven }; } try gop.value_ptr.relocs.append(self.base.allocator, @intCast(u32, dbg_info_buffer.items.len)); - dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 + dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 } - dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string + dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ .dwarf = .{ @@ -2409,7 +2409,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_size), target_endian); } - try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); + try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence }); // Now we have the full contents and may allocate a region to store it. @@ -2493,7 +2493,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven const file_pos = debug_line_sect.sh_offset + src_fn.off; try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); - // .debug_info - End the TAG_subprogram children. + // .debug_info - End the TAG.subprogram children. try dbg_info_buffer.append(0); return self.finishUpdateDecl(module, decl, &dbg_info_type_relocs, &dbg_info_buffer); @@ -2566,34 +2566,34 @@ fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !vo .Bool => { try dbg_info_buffer.appendSlice(&[_]u8{ abbrev_base_type, - DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 - 1, // DW.AT_byte_size, DW.FORM_data1 - 'b', 'o', 'o', 'l', 0, // DW.AT_name, DW.FORM_string + DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1 + 1, // DW.AT.byte_size, DW.FORM.data1 + 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string }); }, .Int => { const info = ty.intInfo(self.base.options.target); try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); - // DW.AT_encoding, DW.FORM_data1 + // DW.AT.encoding, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) { - .signed => DW.ATE_signed, - .unsigned => DW.ATE_unsigned, + .signed => DW.ATE.signed, + .unsigned => DW.ATE.unsigned, }); - // DW.AT_byte_size, DW.FORM_data1 + // DW.AT.byte_size, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); - // DW.AT_name, DW.FORM_string + // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); }, .Optional => { if (ty.isPtrLikeOptional()) { try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); - // DW.AT_encoding, DW.FORM_data1 - dbg_info_buffer.appendAssumeCapacity(DW.ATE_address); - // DW.AT_byte_size, DW.FORM_data1 + // DW.AT.encoding, DW.FORM.data1 + dbg_info_buffer.appendAssumeCapacity(DW.ATE.address); + // DW.AT.byte_size, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); - // DW.AT_name, DW.FORM_string + // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); } else { log.err("TODO implement .debug_info for type '{}'", .{ty}); @@ -3034,7 +3034,7 @@ fn archPtrWidthBytes(self: Elf) u8 { /// The reloc offset for the virtual address of a function in its Line Number Program. /// Size is a virtual address integer. const dbg_line_vaddr_reloc_index = 3; -/// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. +/// The reloc offset for the virtual address of a function in its .debug_info TAG.subprogram. /// Size is a virtual address integer. const dbg_info_low_pc_reloc_index = 1; @@ -3060,7 +3060,7 @@ fn dbgLineNeededHeaderBytes(self: Elf) u32 { const root_src_dir_path_len = if (self.base.options.module.?.root_pkg.root_src_directory.path) |p| p.len else 1; // "." return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + directory_count * 8 + file_name_count * 8 + - // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like + // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. root_src_dir_path_len + self.base.options.module.?.root_pkg.root_src_path.len); @@ -3088,8 +3088,8 @@ fn pwriteDbgLineNops( const tracy = trace(@src()); defer tracy.end(); - const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; - const three_byte_nop = [3]u8{ DW.LNS_advance_pc, 0b1000_0000, 0 }; + const page_of_nops = [1]u8{DW.LNS.negate_stmt} ** 4096; + const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 }; var vecs: [512]std.os.iovec_const = undefined; var vec_index: usize = 0; { diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 025959793e..5f7b119bdc 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -93,7 +93,7 @@ const abbrev_parameter = 6; /// The reloc offset for the virtual address of a function in its Line Number Program. /// Size is a virtual address integer. const dbg_line_vaddr_reloc_index = 3; -/// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. +/// The reloc offset for the virtual address of a function in its .debug_info TAG.subprogram. /// Size is a virtual address integer. const dbg_info_low_pc_reloc_index = 1; @@ -299,40 +299,40 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt // These are LEB encoded but since the values are all less than 127 // we can simply append these bytes. const abbrev_buf = [_]u8{ - abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header - DW.AT_stmt_list, DW.FORM_sec_offset, // offset - DW.AT_low_pc, DW.FORM_addr, - DW.AT_high_pc, DW.FORM_addr, - DW.AT_name, DW.FORM_strp, - DW.AT_comp_dir, DW.FORM_strp, - DW.AT_producer, DW.FORM_strp, - DW.AT_language, DW.FORM_data2, + abbrev_compile_unit, DW.TAG.compile_unit, DW.CHILDREN.yes, // header + DW.AT.stmt_list, DW.FORM.sec_offset, // offset + DW.AT.low_pc, DW.FORM.addr, + DW.AT.high_pc, DW.FORM.addr, + DW.AT.name, DW.FORM.strp, + DW.AT.comp_dir, DW.FORM.strp, + DW.AT.producer, DW.FORM.strp, + DW.AT.language, DW.FORM.data2, 0, 0, // table sentinel - abbrev_subprogram, DW.TAG_subprogram, DW.CHILDREN_yes, // header - DW.AT_low_pc, DW.FORM_addr, // start VM address - DW.AT_high_pc, DW.FORM_data4, - DW.AT_type, DW.FORM_ref4, - DW.AT_name, DW.FORM_string, - DW.AT_decl_line, DW.FORM_data4, - DW.AT_decl_file, DW.FORM_data1, + abbrev_subprogram, DW.TAG.subprogram, DW.CHILDREN.yes, // header + DW.AT.low_pc, DW.FORM.addr, // start VM address + DW.AT.high_pc, DW.FORM.data4, + DW.AT.type, DW.FORM.ref4, + DW.AT.name, DW.FORM.string, + DW.AT.decl_line, DW.FORM.data4, + DW.AT.decl_file, DW.FORM.data1, 0, 0, // table sentinel abbrev_subprogram_retvoid, - DW.TAG_subprogram, DW.CHILDREN_yes, // header - DW.AT_low_pc, DW.FORM_addr, - DW.AT_high_pc, DW.FORM_data4, - DW.AT_name, DW.FORM_string, - DW.AT_decl_line, DW.FORM_data4, - DW.AT_decl_file, DW.FORM_data1, + DW.TAG.subprogram, DW.CHILDREN.yes, // header + DW.AT.low_pc, DW.FORM.addr, + DW.AT.high_pc, DW.FORM.data4, + DW.AT.name, DW.FORM.string, + DW.AT.decl_line, DW.FORM.data4, + DW.AT.decl_file, DW.FORM.data1, 0, 0, // table sentinel - abbrev_base_type, DW.TAG_base_type, DW.CHILDREN_no, // header - DW.AT_encoding, DW.FORM_data1, DW.AT_byte_size, - DW.FORM_data1, DW.AT_name, DW.FORM_string, + abbrev_base_type, DW.TAG.base_type, DW.CHILDREN.no, // header + DW.AT.encoding, DW.FORM.data1, DW.AT.byte_size, + DW.FORM.data1, DW.AT.name, DW.FORM.string, 0, 0, // table sentinel - abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header + abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header 0, 0, // table sentinel - abbrev_parameter, DW.TAG_formal_parameter, DW.CHILDREN_no, // header - DW.AT_location, DW.FORM_exprloc, DW.AT_type, - DW.FORM_ref4, DW.AT_name, DW.FORM_string, + abbrev_parameter, DW.TAG.formal_parameter, DW.CHILDREN.no, // header + DW.AT.location, DW.FORM.exprloc, DW.AT.type, + DW.FORM.ref4, DW.AT.name, DW.FORM.string, 0, 0, // table sentinel 0, 0, 0, // section sentinel }; @@ -397,7 +397,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt const high_pc = text_section.addr + text_section.size; di_buf.appendAssumeCapacity(abbrev_compile_unit); - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT_stmt_list, DW.FORM_sec_offset + mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc); mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), high_pc); mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, name_strp)); @@ -406,7 +406,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: // http://dwarfstd.org/ShowIssue.php?issue=171115.1 // Until then we say it is C99. - mem.writeIntLittle(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99); + mem.writeIntLittle(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG.C99); if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { // Move the first N decls to the end to make more padding for the header. @@ -514,7 +514,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt di_buf.items.len += @sizeOf(u32); // We will come back and write this. const after_header_len = di_buf.items.len; - const opcode_base = DW.LNS_set_isa + 1; + const opcode_base = DW.LNS.set_isa + 1; di_buf.appendSliceAssumeCapacity(&[_]u8{ 1, // minimum_instruction_length 1, // maximum_operations_per_instruction @@ -525,18 +525,18 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt // Standard opcode lengths. The number of items here is based on `opcode_base`. // The value is the number of LEB128 operands the instruction takes. - 0, // `DW.LNS_copy` - 1, // `DW.LNS_advance_pc` - 1, // `DW.LNS_advance_line` - 1, // `DW.LNS_set_file` - 1, // `DW.LNS_set_column` - 0, // `DW.LNS_negate_stmt` - 0, // `DW.LNS_set_basic_block` - 0, // `DW.LNS_const_add_pc` - 1, // `DW.LNS_fixed_advance_pc` - 0, // `DW.LNS_set_prologue_end` - 0, // `DW.LNS_set_epilogue_begin` - 1, // `DW.LNS_set_isa` + 0, // `DW.LNS.copy` + 1, // `DW.LNS.advance_pc` + 1, // `DW.LNS.advance_line` + 1, // `DW.LNS.set_file` + 1, // `DW.LNS.set_column` + 0, // `DW.LNS.negate_stmt` + 0, // `DW.LNS.set_basic_block` + 0, // `DW.LNS.const_add_pc` + 1, // `DW.LNS.fixed_advance_pc` + 0, // `DW.LNS.set_prologue_end` + 0, // `DW.LNS.set_epilogue_begin` + 1, // `DW.LNS.set_isa` 0, // include_directories (none except the compilation unit cwd) }); // file_names[0] @@ -876,22 +876,22 @@ pub fn initDeclDebugBuffers( const line_off = @intCast(u28, decl.src_line + func.lbrace_line); dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ - DW.LNS_extended_op, + DW.LNS.extended_op, @sizeOf(u64) + 1, - DW.LNE_set_address, + DW.LNE.set_address, }); // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); dbg_line_buffer.items.len += @sizeOf(u64); - dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.advance_line); // This is the "relocatable" relative line offset from the previous function's end curly // to this function's begin curly. assert(getRelocDbgLineOff() == dbg_line_buffer.items.len); // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. leb.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); - dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_file); assert(getRelocDbgFileIndex() == dbg_line_buffer.items.len); // Once we support more than one source file, this will have the ability to be more // than one possible value. @@ -900,7 +900,7 @@ pub fn initDeclDebugBuffers( // Emit a line for the begin curly with prologue_end=false. The codegen will // do the work of setting prologue_end=true and epilogue_begin=true. - dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); + dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); // .debug_info subprogram const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1]; @@ -917,9 +917,9 @@ pub fn initDeclDebugBuffers( // "relocations" and have to be in this fixed place so that functions can be // moved in virtual address space. assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); - dbg_info_buffer.items.len += @sizeOf(u64); // DW.AT_low_pc, DW.FORM_addr + dbg_info_buffer.items.len += @sizeOf(u64); // DW.AT.low_pc, DW.FORM.addr assert(getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); - dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 + dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 if (fn_ret_has_bits) { const gop = try dbg_info_type_relocs.getOrPut(allocator, fn_ret_type); if (!gop.found_existing) { @@ -929,11 +929,11 @@ pub fn initDeclDebugBuffers( }; } try gop.value_ptr.relocs.append(allocator, @intCast(u32, dbg_info_buffer.items.len)); - dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 + dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 } - dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string - mem.writeIntLittle(u32, dbg_info_buffer.addManyAsArrayAssumeCapacity(4), line_off + 1); // DW.AT_decl_line, DW.FORM_data4 - dbg_info_buffer.appendAssumeCapacity(file_index); // DW.AT_decl_file, DW.FORM_data1 + dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string + mem.writeIntLittle(u32, dbg_info_buffer.addManyAsArrayAssumeCapacity(4), line_off + 1); // DW.AT.decl_line, DW.FORM.data4 + dbg_info_buffer.appendAssumeCapacity(file_index); // DW.AT.decl_file, DW.FORM.data1 }, else => { // TODO implement .debug_info for global variables @@ -985,16 +985,16 @@ pub fn commitDeclDebugInfo( { // Advance line and PC. // TODO encapsulate logic in a helper function. - try dbg_line_buffer.append(DW.LNS_advance_pc); + try dbg_line_buffer.append(DW.LNS.advance_pc); try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size); - try dbg_line_buffer.append(DW.LNS_advance_line); + try dbg_line_buffer.append(DW.LNS.advance_line); const func = decl.val.castTag(.function).?.data; const line_off = @intCast(u28, func.rbrace_line - func.lbrace_line); try leb.writeULEB128(dbg_line_buffer.writer(), line_off); } - try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); + try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence }); // Now we have the full contents and may allocate a region to store it. @@ -1075,7 +1075,7 @@ pub fn commitDeclDebugInfo( const file_pos = debug_line_sect.offset + src_fn.off; try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); - // .debug_info - End the TAG_subprogram children. + // .debug_info - End the TAG.subprogram children. try dbg_info_buffer.append(0); }, else => {}, @@ -1128,27 +1128,27 @@ fn addDbgInfoType( .Bool => { try dbg_info_buffer.appendSlice(&[_]u8{ abbrev_base_type, - DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 - 1, // DW.AT_byte_size, DW.FORM_data1 + DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1 + 1, // DW.AT.byte_size, DW.FORM.data1 'b', 'o', 'o', 'l', - 0, // DW.AT_name, DW.FORM_string + 0, // DW.AT.name, DW.FORM.string }); }, .Int => { const info = ty.intInfo(target); try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); - // DW.AT_encoding, DW.FORM_data1 + // DW.AT.encoding, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) { - .signed => DW.ATE_signed, - .unsigned => DW.ATE_unsigned, + .signed => DW.ATE.signed, + .unsigned => DW.ATE.unsigned, }); - // DW.AT_byte_size, DW.FORM_data1 + // DW.AT.byte_size, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); - // DW.AT_name, DW.FORM_string + // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); }, else => { @@ -1306,7 +1306,7 @@ fn dbgLineNeededHeaderBytes(self: DebugSymbols, module: *Module) u32 { const root_src_dir_path_len = if (module.root_pkg.root_src_directory.path) |p| p.len else 1; // "." return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + directory_count * 8 + file_name_count * 8 + - // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like + // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. root_src_dir_path_len + module.root_pkg.root_src_path.len); @@ -1332,8 +1332,8 @@ fn pwriteDbgLineNops( const tracy = trace(@src()); defer tracy.end(); - const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; - const three_byte_nop = [3]u8{ DW.LNS_advance_pc, 0b1000_0000, 0 }; + const page_of_nops = [1]u8{DW.LNS.negate_stmt} ** 4096; + const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 }; var vecs: [32]std.os.iovec_const = undefined; var vec_index: usize = 0; { diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 06c76b259d..1051cda694 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -836,8 +836,8 @@ pub fn parseDebugInfo(self: *Object, allocator: *Allocator) !void { }, else => |e| return e, }; - const name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT_name); - const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT_comp_dir); + const name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.name); + const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir); self.debug_info = debug_info; self.tu_name = try allocator.dupe(u8, name); diff --git a/test/behavior.zig b/test/behavior.zig index 7028d6cbf6..80de1880d8 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -10,6 +10,7 @@ test { _ = @import("behavior/if.zig"); _ = @import("behavior/cast.zig"); _ = @import("behavior/array.zig"); + _ = @import("behavior/usingnamespace.zig"); if (!builtin.zig_is_stage2) { // Tests that only pass for stage1. @@ -148,7 +149,7 @@ test { _ = @import("behavior/undefined.zig"); _ = @import("behavior/underscore.zig"); _ = @import("behavior/union.zig"); - _ = @import("behavior/usingnamespace.zig"); + _ = @import("behavior/usingnamespace_stage1.zig"); _ = @import("behavior/var_args.zig"); _ = @import("behavior/vector.zig"); _ = @import("behavior/void.zig"); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 1b6540cd32..0d103bc49a 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -125,12 +125,6 @@ test "pointer to type" { } } -test "no undeclared identifier error in unanalyzed branches" { - if (false) { - lol_this_doesnt_exist = nonsense; - } -} - test "a type constructed in a global expression" { var l: List = undefined; l.array[0] = 10; diff --git a/test/behavior/usingnamespace.zig b/test/behavior/usingnamespace.zig index b529b24dd4..e819566002 100644 --- a/test/behavior/usingnamespace.zig +++ b/test/behavior/usingnamespace.zig @@ -1,22 +1,13 @@ const std = @import("std"); -fn Foo(comptime T: type) type { - return struct { - usingnamespace T; - }; -} - -test "usingnamespace inside a generic struct" { - const std2 = Foo(std); - const testing2 = Foo(std.testing); - try std2.testing.expect(true); - try testing2.expect(true); -} +const A = struct { + pub const B = bool; +}; -usingnamespace struct { - pub const foo = 42; +const C = struct { + usingnamespace A; }; -test "usingnamespace does not redeclare an imported variable" { - comptime try std.testing.expect(foo == 42); +test "basic usingnamespace" { + try std.testing.expect(C.B == bool); } diff --git a/test/behavior/usingnamespace_stage1.zig b/test/behavior/usingnamespace_stage1.zig new file mode 100644 index 0000000000..b529b24dd4 --- /dev/null +++ b/test/behavior/usingnamespace_stage1.zig @@ -0,0 +1,22 @@ +const std = @import("std"); + +fn Foo(comptime T: type) type { + return struct { + usingnamespace T; + }; +} + +test "usingnamespace inside a generic struct" { + const std2 = Foo(std); + const testing2 = Foo(std.testing); + try std2.testing.expect(true); + try testing2.expect(true); +} + +usingnamespace struct { + pub const foo = 42; +}; + +test "usingnamespace does not redeclare an imported variable" { + comptime try std.testing.expect(foo == 42); +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 4c55e39ac7..82ee089970 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -8846,4 +8846,14 @@ pub fn addCases(ctx: *TestContext) !void { , &[_][]const u8{ "error: invalid operands to binary expression: 'f32' and 'f32'", }); + + ctx.objErrStage1("undeclared identifier in unanalyzed branch", + \\export fn a() void { + \\ if (false) { + \\ lol_this_doesnt_exist = nonsense; + \\ } + \\} + , &[_][]const u8{ + "tmp.zig:3:9: error: use of undeclared identifier 'lol_this_doesnt_exist'", + }); } -- cgit v1.2.3 From e41e75a4862e955266a7e760133ea757e5afb8ce Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 30 Aug 2021 18:47:00 -0700 Subject: stage2: update for new usingnamespace semantics --- src/AstGen.zig | 8 -------- src/clang_options_data.zig | 8 +++++++- src/codegen/spirv/spec.zig | 4 ++-- src/libc_installation.zig | 6 +++--- src/link/MachO/DebugSymbols.zig | 5 ++++- src/link/tapi/parse/test.zig | 4 ++-- src/type.zig | 2 +- src/value.zig | 2 +- src/windows_sdk.zig | 21 +++++++++++++-------- tools/update_clang_options.zig | 8 +++++++- 10 files changed, 40 insertions(+), 28 deletions(-) (limited to 'src/codegen') diff --git a/src/AstGen.zig b/src/AstGen.zig index c96a97ddeb..570b2cd943 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -9072,14 +9072,6 @@ const GenZir = struct { return @intCast(u32, gz.decl_line + astgen.source_line); } - fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc { - return .{ .token_offset = token_index - gz.srcToken() }; - } - - fn nodeSrcLoc(gz: GenZir, node_index: ast.Node.Index) LazySrcLoc { - return .{ .node_offset = gz.nodeIndexToRelative(node_index) }; - } - fn nodeIndexToRelative(gz: GenZir, node_index: ast.Node.Index) i32 { return @bitCast(i32, node_index) - @bitCast(i32, gz.decl_node_index); } diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig index eb8dfc5753..524374a7e9 100644 --- a/src/clang_options_data.zig +++ b/src/clang_options_data.zig @@ -1,6 +1,12 @@ // This file is generated by tools/update_clang_options.zig. // zig fmt: off -usingnamespace @import("clang_options.zig"); +const clang_options = @import("clang_options.zig"); +const CliArg = clang_options.CliArg; +const flagpd1 = clang_options.flagpd1; +const flagpsl = clang_options.flagpsl; +const joinpd1 = clang_options.joinpd1; +const jspd1 = clang_options.jspd1; +const sepd1 = clang_options.sepd1; pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{ flagpd1("C"), flagpd1("CC"), diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig index 429ed63d23..26d1925646 100644 --- a/src/codegen/spirv/spec.zig +++ b/src/codegen/spirv/spec.zig @@ -582,8 +582,8 @@ pub const Opcode = enum(u16) { OpSpecConstantCompositeContinuedINTEL = 6092, _, - const OpReportIntersectionKHR = OpReportIntersectionNV; - const OpTypeAccelerationStructureKHR = OpTypeAccelerationStructureNV; + const OpReportIntersectionKHR: Opcode = .OpReportIntersectionNV; + const OpTypeAccelerationStructureKHR: Opcode = .OpTypeAccelerationStructureNV; }; pub const ImageOperands = packed struct { Bias: bool align(@alignOf(u32)) = false, diff --git a/src/libc_installation.zig b/src/libc_installation.zig index b639e0f2f8..c011abbfcc 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -12,7 +12,7 @@ const is_haiku = Target.current.os.tag == .haiku; const log = std.log.scoped(.libc_installation); -usingnamespace @import("windows_sdk.zig"); +const ZigWindowsSDK = @import("windows_sdk.zig").ZigWindowsSDK; /// See the render function implementation for documentation of the fields. pub const LibCInstallation = struct { @@ -183,9 +183,9 @@ pub const LibCInstallation = struct { if (!build_options.have_llvm) return error.WindowsSdkNotFound; var sdk: *ZigWindowsSDK = undefined; - switch (zig_find_windows_sdk(&sdk)) { + switch (ZigWindowsSDK.find(&sdk)) { .None => { - defer zig_free_windows_sdk(sdk); + defer sdk.free(); var batch = Batch(FindError!void, 5, .auto_async).init(); batch.add(&async self.findNativeMsvcIncludeDir(args, sdk)); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 5f7b119bdc..ee99adafaa 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -20,7 +20,10 @@ const SrcFn = MachO.SrcFn; const TextBlock = MachO.TextBlock; const padToIdeal = MachO.padToIdeal; -usingnamespace @import("commands.zig"); +const commands = @import("commands.zig"); +const emptyHeader = commands.emptyHeader; +const LoadCommand = commands.LoadCommand; +const SegmentCommand = commands.SegmentCommand; const page_size: u16 = 0x1000; diff --git a/src/link/tapi/parse/test.zig b/src/link/tapi/parse/test.zig index b96a71fe97..fc0bed5df6 100644 --- a/src/link/tapi/parse/test.zig +++ b/src/link/tapi/parse/test.zig @@ -1,8 +1,8 @@ const std = @import("std"); const mem = std.mem; const testing = std.testing; - -usingnamespace @import("../parse.zig"); +const Tree = @import("../parse.zig").Tree; +const Node = @import("../parse.zig").Node; test "explicit doc" { const source = diff --git a/src/type.zig b/src/type.zig index aa4517ab05..b6602ba18d 100644 --- a/src/type.zig +++ b/src/type.zig @@ -197,7 +197,7 @@ pub const Type = extern union { /// Prefer `castTag` to this. pub fn cast(self: Type, comptime T: type) ?*T { if (@hasField(T, "base_tag")) { - return base.castTag(T.base_tag); + return self.castTag(T.base_tag); } if (self.tag_if_small_enough < Tag.no_payload_count) { return null; diff --git a/src/value.zig b/src/value.zig index 5ac9f142c4..8aaf70c428 100644 --- a/src/value.zig +++ b/src/value.zig @@ -315,7 +315,7 @@ pub const Value = extern union { /// Prefer `castTag` to this. pub fn cast(self: Value, comptime T: type) ?*T { if (@hasField(T, "base_tag")) { - return base.castTag(T.base_tag); + return self.castTag(T.base_tag); } if (self.tag_if_small_enough < Tag.no_payload_count) { return null; diff --git a/src/windows_sdk.zig b/src/windows_sdk.zig index ca69ff4548..3ff53dc2e1 100644 --- a/src/windows_sdk.zig +++ b/src/windows_sdk.zig @@ -11,12 +11,17 @@ pub const ZigWindowsSDK = extern struct { version81_len: usize, msvc_lib_dir_ptr: ?[*]const u8, msvc_lib_dir_len: usize, + + pub const find = zig_find_windows_sdk; + pub const free = zig_free_windows_sdk; + + pub const FindError = enum(c_int) { + None, + OutOfMemory, + NotFound, + PathTooLong, + }; + + extern fn zig_find_windows_sdk(out_sdk: **ZigWindowsSDK) FindError; + extern fn zig_free_windows_sdk(sdk: *ZigWindowsSDK) void; }; -pub const ZigFindWindowsSdkError = enum(c_int) { - None, - OutOfMemory, - NotFound, - PathTooLong, -}; -pub extern fn zig_find_windows_sdk(out_sdk: **ZigWindowsSDK) ZigFindWindowsSdkError; -pub extern fn zig_free_windows_sdk(sdk: *ZigWindowsSDK) void; diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index 04cdbf44de..407e813ef3 100644 --- a/tools/update_clang_options.zig +++ b/tools/update_clang_options.zig @@ -473,7 +473,13 @@ pub fn main() anyerror!void { try stdout.writeAll( \\// This file is generated by tools/update_clang_options.zig. \\// zig fmt: off - \\usingnamespace @import("clang_options.zig"); + \\const clang_options = @import("clang_options.zig"); + \\const CliArg = clang_options.CliArg; + \\const flagpd1 = clang_options.flagpd1; + \\const flagpsl = clang_options.flagpsl; + \\const joinpd1 = clang_options.joinpd1; + \\const jspd1 = clang_options.jspd1; + \\const sepd1 = clang_options.sepd1; \\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{ \\ ); -- cgit v1.2.3