aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Liveness.zig3
-rw-r--r--src/Module.zig11
-rw-r--r--src/Sema.zig42
-rw-r--r--src/arch/aarch64/CodeGen.zig3
-rw-r--r--src/codegen.zig3
-rw-r--r--src/codegen/c.zig3
-rw-r--r--src/codegen/llvm.zig5
-rw-r--r--src/print_air.zig19
8 files changed, 61 insertions, 28 deletions
diff --git a/src/Liveness.zig b/src/Liveness.zig
index 5f0919a6cb..499500fddb 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -267,7 +267,6 @@ fn analyzeInst(
.set_union_tag,
.min,
.max,
- .slice,
=> {
const o = inst_datas[inst].bin_op;
return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none });
@@ -363,7 +362,7 @@ fn analyzeInst(
const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;
return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none });
},
- .ptr_elem_ptr, .slice_elem_ptr => {
+ .ptr_elem_ptr, .slice_elem_ptr, .slice => {
const extra = a.air.extraData(Air.Bin, inst_datas[inst].ty_pl.payload).data;
return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
},
diff --git a/src/Module.zig b/src/Module.zig
index 3ac523bdc5..de6770d3d7 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -772,6 +772,17 @@ pub const Decl = struct {
else => false,
};
}
+
+ pub fn getAlignment(decl: Decl, target: Target) u32 {
+ assert(decl.has_tv);
+ if (decl.align_val.tag() != .null_value) {
+ // Explicit alignment.
+ return @intCast(u32, decl.align_val.toUnsignedInt());
+ } else {
+ // Natural alignment.
+ return decl.ty.abiAlignment(target);
+ }
+ }
};
/// This state is attached to every Decl when Module emit_h is non-null.
diff --git a/src/Sema.zig b/src/Sema.zig
index 92a3a6a50f..9bd0e1037d 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -11925,18 +11925,37 @@ fn coerce(
return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
}
+ // *T to *[1]T
+ single_item: {
+ if (!dest_ty.isSinglePointer()) break :single_item;
+ if (!inst_ty.isSinglePointer()) break :single_item;
+ const ptr_elem_ty = inst_ty.childType();
+ const array_ty = dest_ty.childType();
+ if (array_ty.zigTypeTag() != .Array) break :single_item;
+ const array_elem_ty = array_ty.childType();
+ const dest_is_mut = !dest_ty.isConstPtr();
+ if (inst_ty.isConstPtr() and dest_is_mut) break :single_item;
+ if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :single_item;
+ if (inst_ty.ptrAddressSpace() != dest_ty.ptrAddressSpace()) break :single_item;
+ switch (coerceInMemoryAllowed(array_elem_ty, ptr_elem_ty, dest_is_mut, target)) {
+ .ok => {},
+ .no_match => break :single_item,
+ }
+ return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
+ }
+
// Coercions where the source is a single pointer to an array.
src_array_ptr: {
if (!inst_ty.isSinglePointer()) break :src_array_ptr;
- const array_type = inst_ty.elemType();
- if (array_type.zigTypeTag() != .Array) break :src_array_ptr;
- const array_elem_type = array_type.elemType();
+ const array_ty = inst_ty.childType();
+ if (array_ty.zigTypeTag() != .Array) break :src_array_ptr;
+ const array_elem_type = array_ty.childType();
const dest_is_mut = !dest_ty.isConstPtr();
if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr;
if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :src_array_ptr;
if (inst_ty.ptrAddressSpace() != dest_ty.ptrAddressSpace()) break :src_array_ptr;
- const dst_elem_type = dest_ty.elemType();
+ const dst_elem_type = dest_ty.childType();
switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) {
.ok => {},
.no_match => break :src_array_ptr,
@@ -11949,20 +11968,20 @@ fn coerce(
},
.C => {
// *[N]T to [*c]T
- return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src);
+ return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
},
.Many => {
// *[N]T to [*]T
// *[N:s]T to [*:s]T
// *[N:s]T to [*]T
if (dest_ty.sentinel()) |dst_sentinel| {
- if (array_type.sentinel()) |src_sentinel| {
+ if (array_ty.sentinel()) |src_sentinel| {
if (src_sentinel.eql(dst_sentinel, dst_elem_type)) {
- return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src);
+ return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
}
}
} else {
- return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src);
+ return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
}
},
.One => {},
@@ -12680,7 +12699,7 @@ fn coerceArrayPtrToSlice(
return block.addTyOp(.array_to_slice, dest_ty, inst);
}
-fn coerceArrayPtrToMany(
+fn coerceCompatiblePtrs(
sema: *Sema,
block: *Block,
dest_ty: Type,
@@ -12888,10 +12907,15 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
const decl_tv = try decl.typedValue();
if (decl_tv.val.castTag(.variable)) |payload| {
const variable = payload.data;
+ const alignment: u32 = if (decl.align_val.tag() == .null_value)
+ 0
+ else
+ @intCast(u32, decl.align_val.toUnsignedInt());
const ty = try Type.ptr(sema.arena, .{
.pointee_type = decl_tv.ty,
.mutable = variable.is_mutable,
.@"addrspace" = decl.@"addrspace",
+ .@"align" = alignment,
});
return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
}
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 155ac6de68..2c6feec70c 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -876,7 +876,8 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
}
fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
- const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch});
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
diff --git a/src/codegen.zig b/src/codegen.zig
index ac9eaeda2a..5f5ee1b549 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -1246,7 +1246,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
- const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
else => return self.fail("TODO implement slice for {}", .{self.target.cpu.arch}),
};
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index aa1ece7ba3..dd71590566 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1663,7 +1663,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValu
fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
- const bin_op = f.air.instructions.items(.data)[inst].bin_op;
+ const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
+ const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
const ptr = try f.resolveInst(bin_op.lhs);
const len = try f.resolveInst(bin_op.rhs);
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index d6b41208f2..3f24bb535d 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -581,7 +581,9 @@ pub const DeclGen = struct {
} else if (decl.val.castTag(.extern_fn)) |extern_fn| {
_ = try self.resolveLlvmFunction(extern_fn.data);
} else {
+ const target = self.module.getTarget();
const global = try self.resolveGlobalDecl(decl);
+ global.setAlignment(decl.getAlignment(target));
assert(decl.has_tv);
const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
const variable = payload.data;
@@ -2713,7 +2715,8 @@ pub const FuncGen = struct {
fn airSlice(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 ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
const ptr = try self.resolveInst(bin_op.lhs);
const len = try self.resolveInst(bin_op.rhs);
const inst_ty = self.air.typeOfIndex(inst);
diff --git a/src/print_air.zig b/src/print_air.zig
index 5aec562241..17efa8297d 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -141,7 +141,6 @@ const Writer = struct {
.set_union_tag,
.min,
.max,
- .slice,
=> try w.writeBinOp(s, inst),
.is_null,
@@ -203,8 +202,11 @@ const Writer = struct {
.loop,
=> try w.writeBlock(s, inst),
- .slice_elem_ptr => try w.writeSliceElemPtr(s, inst),
- .ptr_elem_ptr => try w.writePtrElemPtr(s, inst),
+ .slice,
+ .slice_elem_ptr,
+ .ptr_elem_ptr,
+ => try w.writeTyPlBin(s, inst),
+
.struct_field_ptr => try w.writeStructField(s, inst),
.struct_field_val => try w.writeStructField(s, inst),
.constant => try w.writeConstant(s, inst),
@@ -285,16 +287,7 @@ const Writer = struct {
try s.print(", {d}", .{extra.field_index});
}
- fn writeSliceElemPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
- const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
- const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;
-
- try w.writeOperand(s, inst, 0, extra.lhs);
- try s.writeAll(", ");
- try w.writeOperand(s, inst, 1, extra.rhs);
- }
-
- fn writePtrElemPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
+ fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;