aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig6
-rw-r--r--src/codegen/llvm.zig23
-rw-r--r--src/target.zig19
-rw-r--r--src/type.zig10
4 files changed, 41 insertions, 17 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index c6c7a94b41..99b502dbd7 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1024,10 +1024,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
if (options.use_llvm) |explicit|
break :blk explicit;
- // If we are outputting .c code we must use Zig backend.
- if (ofmt == .c)
- break :blk false;
-
// If emitting to LLVM bitcode object format, must use LLVM backend.
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null)
break :blk true;
@@ -1042,7 +1038,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
break :blk true;
// If LLVM does not support the target, then we can't use it.
- if (!target_util.hasLlvmSupport(options.target))
+ if (!target_util.hasLlvmSupport(options.target, ofmt))
break :blk false;
// Prefer LLVM for release builds.
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 7f85570e06..c3194ccda1 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -768,7 +768,11 @@ pub const Object = struct {
if (ptr_info.@"align" != 0) {
dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
} else {
- dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.pointee_type.abiAlignment(target));
+ const elem_align = @maximum(
+ ptr_info.pointee_type.abiAlignment(target),
+ 1,
+ );
+ dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);
}
}
}
@@ -840,7 +844,8 @@ pub const Object = struct {
if (ptr_info.@"align" != 0) {
dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
} else {
- dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.pointee_type.abiAlignment(target));
+ const elem_align = @maximum(ptr_info.pointee_type.abiAlignment(target), 1);
+ dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);
}
const ptr_param = llvm_func.getParam(llvm_arg_i);
llvm_arg_i += 1;
@@ -3401,6 +3406,13 @@ pub const DeclGen = struct {
const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, dg.module).?;
assert(union_obj.haveFieldTypes());
+
+ // Sometimes we must make an unnamed struct because LLVM does
+ // not support bitcasting our payload struct to the true union payload type.
+ // Instead we use an unnamed struct and every reference to the global
+ // must pointer cast to the expected type before accessing the union.
+ var need_unnamed: bool = layout.most_aligned_field != field_index;
+
const field_ty = union_obj.fields.values()[field_index].ty;
const payload = p: {
if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
@@ -3408,6 +3420,7 @@ pub const DeclGen = struct {
break :p dg.context.intType(8).arrayType(padding_len).getUndef();
}
const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
+ need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field);
const field_size = field_ty.abiSize(target);
if (field_size == layout.payload_size) {
break :p field;
@@ -3419,12 +3432,6 @@ pub const DeclGen = struct {
break :p dg.context.constStruct(&fields, fields.len, .True);
};
- // In this case we must make an unnamed struct because LLVM does
- // not support bitcasting our payload struct to the true union payload type.
- // Instead we use an unnamed struct and every reference to the global
- // must pointer cast to the expected type before accessing the union.
- const need_unnamed = layout.most_aligned_field != field_index;
-
if (layout.tag_size == 0) {
const fields: [1]*const llvm.Value = .{payload};
if (need_unnamed) {
diff --git a/src/target.zig b/src/target.zig
index 93c179b7f0..ea8b3efc45 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -204,7 +204,24 @@ pub fn hasValgrindSupport(target: std.Target) bool {
/// The set of targets that LLVM has non-experimental support for.
/// Used to select between LLVM backend and self-hosted backend when compiling in
/// release modes.
-pub fn hasLlvmSupport(target: std.Target) bool {
+pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool {
+ switch (ofmt) {
+ // LLVM does not support these object formats:
+ .c,
+ .plan9,
+ => return false,
+
+ .coff,
+ .elf,
+ .macho,
+ .wasm,
+ .spirv,
+ .hex,
+ .raw,
+ .nvptx,
+ => {},
+ }
+
return switch (target.cpu.arch) {
.arm,
.armeb,
diff --git a/src/type.zig b/src/type.zig
index 50302dca6c..55466efe4a 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -2906,9 +2906,13 @@ pub const Type = extern union {
.array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),
- // TODO audit this - is there any more complicated logic to determine
- // ABI alignment of vectors?
- .vector => return AbiAlignmentAdvanced{ .scalar = 16 },
+ .vector => {
+ const len = ty.arrayLen();
+ const bits = try bitSizeAdvanced(ty.elemType(), target, sema_kit);
+ const bytes = (bits + 7) / 8;
+ const alignment = std.math.ceilPowerOfTwoAssert(u64, bytes * len);
+ return AbiAlignmentAdvanced{ .scalar = @intCast(u32, alignment) };
+ },
.i16, .u16 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(16, target) },
.u29 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(29, target) },