Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit LLVM bitcode without using LLVM #16804

Closed
wants to merge 10 commits into from
37 changes: 26 additions & 11 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,18 @@ pub const Object = struct {
if (emit_asm_path == null and emit_bin_path == null and
emit_llvm_ir_path == null and emit_llvm_bc_path == null) return;

if (emit_llvm_bc_path) |path| {
if (!self.builder.useLibLlvm()) {
var file = try std.fs.cwd().createFileZ(path, .{});
defer file.close();
const bitcode = try self.builder.toBitcode(arena);

const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
try file.writeAll(ptr[0..(bitcode.len * 4)]);
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return;
if (emit_asm_path == null and emit_bin_path == null and emit_llvm_ir_path == null) return;

It will eventually be the frontend's responsibility to check if the requested emits are invalid, but for now, not creating an expected output file and returning success here will just confuse the build system.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree, that return was mostly for testing. I'll change it to handle it more reasonably.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I figured, feel free to not resolve it until this is ready for review.

}
}

if (!self.builder.useLibLlvm()) {
log.err("emitting without libllvm not implemented", .{});
return error.FailedToEmit;
Expand Down Expand Up @@ -3253,22 +3265,19 @@ pub const Object = struct {
},
.simple_type => unreachable,
.struct_type => |struct_type| {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
if (o.type_map.get(t.toIntern())) |value| return value;

const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
if (struct_obj.layout == .Packed) {
assert(struct_obj.haveLayout());
const int_ty = try o.lowerType(struct_obj.backing_int_ty);
gop.value_ptr.* = int_ty;
try o.type_map.put(o.gpa, t.toIntern(), int_ty);
return int_ty;
}

const name = try o.builder.string(ip.stringToSlice(
try struct_obj.getFullyQualifiedName(mod),
));
const ty = try o.builder.opaqueType(name);
gop.value_ptr.* = ty; // must be done before any recursive calls

assert(struct_obj.haveFieldTypes());

Expand Down Expand Up @@ -3310,6 +3319,9 @@ pub const Object = struct {
);
}

const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);

try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(struct_kind, llvm_field_types.items),
Expand Down Expand Up @@ -3354,29 +3366,26 @@ pub const Object = struct {
return o.builder.structType(.normal, llvm_field_types.items);
},
.union_type => |union_type| {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
if (o.type_map.get(t.toIntern())) |value| return value;

const union_obj = ip.loadUnionType(union_type);
const layout = mod.getUnionLayout(union_obj);

if (union_obj.flagsPtr(ip).layout == .Packed) {
const int_ty = try o.builder.intType(@intCast(t.bitSize(mod)));
gop.value_ptr.* = int_ty;
try o.type_map.put(o.gpa, t.toIntern(), int_ty);
return int_ty;
}

if (layout.payload_size == 0) {
const enum_tag_ty = try o.lowerType(union_obj.enum_tag_ty.toType());
gop.value_ptr.* = enum_tag_ty;
try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
return enum_tag_ty;
}

const name = try o.builder.string(ip.stringToSlice(
try mod.declPtr(union_obj.decl).getFullyQualifiedName(mod),
));
const ty = try o.builder.opaqueType(name);
gop.value_ptr.* = ty; // must be done before any recursive calls

const aligned_field_ty = union_obj.field_types.get(ip)[layout.most_aligned_field].toType();
const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
Expand All @@ -3396,6 +3405,9 @@ pub const Object = struct {
};

if (layout.tag_size == 0) {
const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);

try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(.normal, &.{payload_ty}),
Expand All @@ -3421,6 +3433,9 @@ pub const Object = struct {
llvm_fields_len += 1;
}

const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);

try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(.normal, llvm_fields[0..llvm_fields_len]),
Expand Down
Loading
Loading