mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #11442 from Vexu/stage3
Make self hosted compiler capable of building itself
This commit is contained in:
commit
578a792b33
@ -219,7 +219,11 @@ pub extern "c" fn utimes(path: [*:0]const u8, times: *[2]c.timeval) c_int;
|
||||
pub extern "c" fn utimensat(dirfd: c.fd_t, pathname: [*:0]const u8, times: *[2]c.timespec, flags: u32) c_int;
|
||||
pub extern "c" fn futimens(fd: c.fd_t, times: *const [2]c.timespec) c_int;
|
||||
|
||||
pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const c.pthread_attr_t, start_routine: fn (?*anyopaque) callconv(.C) ?*anyopaque, noalias arg: ?*anyopaque) c.E;
|
||||
pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const c.pthread_attr_t, start_routine: PThreadStartFn, noalias arg: ?*anyopaque) c.E;
|
||||
const PThreadStartFn = if (builtin.zig_backend == .stage1)
|
||||
fn (?*anyopaque) callconv(.C) ?*anyopaque
|
||||
else
|
||||
*const fn (?*anyopaque) callconv(.C) ?*anyopaque;
|
||||
pub extern "c" fn pthread_attr_init(attr: *c.pthread_attr_t) c.E;
|
||||
pub extern "c" fn pthread_attr_setstack(attr: *c.pthread_attr_t, stackaddr: *anyopaque, stacksize: usize) c.E;
|
||||
pub extern "c" fn pthread_attr_setstacksize(attr: *c.pthread_attr_t, stacksize: usize) c.E;
|
||||
@ -229,10 +233,14 @@ pub extern "c" fn pthread_self() pthread_t;
|
||||
pub extern "c" fn pthread_join(thread: pthread_t, arg_return: ?*?*anyopaque) c.E;
|
||||
pub extern "c" fn pthread_detach(thread: pthread_t) c.E;
|
||||
pub extern "c" fn pthread_atfork(
|
||||
prepare: ?fn () callconv(.C) void,
|
||||
parent: ?fn () callconv(.C) void,
|
||||
child: ?fn () callconv(.C) void,
|
||||
prepare: ?PThreadForkFn,
|
||||
parent: ?PThreadForkFn,
|
||||
child: ?PThreadForkFn,
|
||||
) c_int;
|
||||
const PThreadForkFn = if (builtin.zig_backend == .stage1)
|
||||
fn () callconv(.C) void
|
||||
else
|
||||
*const fn () callconv(.C) void;
|
||||
pub extern "c" fn pthread_key_create(key: *c.pthread_key_t, destructor: ?fn (value: *anyopaque) callconv(.C) void) c.E;
|
||||
pub extern "c" fn pthread_key_delete(key: c.pthread_key_t) c.E;
|
||||
pub extern "c" fn pthread_getspecific(key: c.pthread_key_t) ?*anyopaque;
|
||||
|
||||
@ -126,7 +126,11 @@ pub const Token = struct {
|
||||
Keyword_error,
|
||||
Keyword_pragma,
|
||||
|
||||
pub fn symbol(id: std.meta.Tag(Id)) []const u8 {
|
||||
pub fn symbol(id: Id) []const u8 {
|
||||
return symbolName(id);
|
||||
}
|
||||
|
||||
pub fn symbolName(id: std.meta.Tag(Id)) []const u8 {
|
||||
return switch (id) {
|
||||
.Invalid => "Invalid",
|
||||
.Eof => "Eof",
|
||||
|
||||
@ -32,10 +32,8 @@ comptime {
|
||||
@export(wasm_start, .{ .name = "_start", .linkage = .Strong });
|
||||
}
|
||||
|
||||
if (builtin.zig_backend == .stage1) { // TODO remove this condition
|
||||
if (native_os == .linux) {
|
||||
@export(clone, .{ .name = "clone" });
|
||||
}
|
||||
if (native_os == .linux) {
|
||||
@export(clone, .{ .name = "clone" });
|
||||
}
|
||||
|
||||
@export(memset, .{ .name = "memset", .linkage = .Strong });
|
||||
|
||||
@ -1807,6 +1807,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
|
||||
.@"break";
|
||||
|
||||
if (rhs == 0) {
|
||||
try genDefers(parent_gz, scope, parent_scope, .normal_only);
|
||||
|
||||
_ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
|
||||
return Zir.Inst.Ref.unreachable_value;
|
||||
}
|
||||
@ -1819,12 +1821,15 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
|
||||
const prev_rvalue_noresult = parent_gz.rvalue_noresult;
|
||||
parent_gz.rvalue_noresult = .none;
|
||||
const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node);
|
||||
const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
|
||||
parent_gz.rvalue_noresult = prev_rvalue_noresult;
|
||||
|
||||
try genDefers(parent_gz, scope, parent_scope, .normal_only);
|
||||
|
||||
switch (block_gz.break_result_loc) {
|
||||
.block_ptr => {
|
||||
const br = try parent_gz.addBreak(break_tag, block_inst, operand);
|
||||
try block_gz.labeled_breaks.append(astgen.gpa, br);
|
||||
try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index });
|
||||
},
|
||||
.ptr => {
|
||||
// In this case we don't have any mechanism to intercept it;
|
||||
@ -1843,13 +1848,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
|
||||
.local_val => scope = scope.cast(Scope.LocalVal).?.parent,
|
||||
.local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
|
||||
.namespace => break,
|
||||
.defer_normal => {
|
||||
const defer_scope = scope.cast(Scope.Defer).?;
|
||||
scope = defer_scope.parent;
|
||||
const expr_node = node_datas[defer_scope.defer_node].rhs;
|
||||
try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node);
|
||||
},
|
||||
.defer_error => scope = scope.cast(Scope.Defer).?.parent,
|
||||
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
|
||||
.top => unreachable,
|
||||
}
|
||||
}
|
||||
@ -2030,7 +2029,7 @@ fn labeledBlockExpr(
|
||||
// The code took advantage of the result location as a pointer.
|
||||
// Turn the break instruction operands into void.
|
||||
for (block_scope.labeled_breaks.items) |br| {
|
||||
zir_datas[br].@"break".operand = .void_value;
|
||||
zir_datas[br.br].@"break".operand = .void_value;
|
||||
}
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
|
||||
@ -2047,17 +2046,17 @@ fn labeledBlockExpr(
|
||||
for (block_scope.labeled_breaks.items) |br| {
|
||||
// We expect the `store_to_block_ptr` to be created between 1-3 instructions
|
||||
// prior to the break.
|
||||
var search_index = br -| 3;
|
||||
while (search_index < br) : (search_index += 1) {
|
||||
var search_index = br.search -| 3;
|
||||
while (search_index < br.search) : (search_index += 1) {
|
||||
if (zir_tags[search_index] == .store_to_block_ptr and
|
||||
zir_datas[search_index].bin.lhs == block_scope.rl_ptr)
|
||||
{
|
||||
zir_tags[search_index] = .as;
|
||||
zir_datas[search_index].bin = .{
|
||||
.lhs = block_scope.rl_ty_inst,
|
||||
.rhs = zir_datas[br].@"break".operand,
|
||||
.rhs = zir_datas[br.br].@"break".operand,
|
||||
};
|
||||
zir_datas[br].@"break".operand = indexToRef(search_index);
|
||||
zir_datas[br.br].@"break".operand = indexToRef(search_index);
|
||||
break;
|
||||
}
|
||||
} else unreachable;
|
||||
@ -9719,7 +9718,7 @@ const GenZir = struct {
|
||||
break_count: usize = 0,
|
||||
/// Tracks `break :foo bar` instructions so they can possibly be elided later if
|
||||
/// the labeled block ends up not needing a result location pointer.
|
||||
labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{},
|
||||
labeled_breaks: ArrayListUnmanaged(struct { br: Zir.Inst.Index, search: Zir.Inst.Index }) = .{},
|
||||
|
||||
suspend_node: Ast.Node.Index = 0,
|
||||
nosuspend_node: Ast.Node.Index = 0,
|
||||
|
||||
@ -161,7 +161,12 @@ pub const ASTUnit = opaque {
|
||||
extern fn ZigClangASTUnit_getSourceManager(*ASTUnit) *SourceManager;
|
||||
|
||||
pub const visitLocalTopLevelDecls = ZigClangASTUnit_visitLocalTopLevelDecls;
|
||||
extern fn ZigClangASTUnit_visitLocalTopLevelDecls(*ASTUnit, context: ?*anyopaque, Fn: ?fn (?*anyopaque, *const Decl) callconv(.C) bool) bool;
|
||||
extern fn ZigClangASTUnit_visitLocalTopLevelDecls(*ASTUnit, context: ?*anyopaque, Fn: ?VisitorFn) bool;
|
||||
|
||||
const VisitorFn = if (@import("builtin").zig_backend == .stage1)
|
||||
fn (?*anyopaque, *const Decl) callconv(.C) bool
|
||||
else
|
||||
*const fn (?*anyopaque, *const Decl) callconv(.C) bool;
|
||||
|
||||
pub const getLocalPreprocessingEntities_begin = ZigClangASTUnit_getLocalPreprocessingEntities_begin;
|
||||
extern fn ZigClangASTUnit_getLocalPreprocessingEntities_begin(*ASTUnit) PreprocessingRecord.iterator;
|
||||
@ -490,8 +495,8 @@ pub const FloatingLiteral = opaque {
|
||||
pub const getValueAsApproximateDouble = ZigClangFloatingLiteral_getValueAsApproximateDouble;
|
||||
extern fn ZigClangFloatingLiteral_getValueAsApproximateDouble(*const FloatingLiteral) f64;
|
||||
|
||||
pub const getBeginLoc = ZigClangIntegerLiteral_getBeginLoc;
|
||||
extern fn ZigClangIntegerLiteral_getBeginLoc(*const FloatingLiteral) SourceLocation;
|
||||
pub const getBeginLoc = ZigClangFloatingLiteral_getBeginLoc;
|
||||
extern fn ZigClangFloatingLiteral_getBeginLoc(*const FloatingLiteral) SourceLocation;
|
||||
|
||||
pub const getRawSemantics = ZigClangFloatingLiteral_getRawSemantics;
|
||||
extern fn ZigClangFloatingLiteral_getRawSemantics(*const FloatingLiteral) APFloatBaseSemantics;
|
||||
|
||||
@ -4732,10 +4732,11 @@ pub const FuncGen = struct {
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
const payload_ty = optional_ty.optionalChild(&buf);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand;
|
||||
if (invert) {
|
||||
return self.builder.buildNot(operand, "");
|
||||
return self.builder.buildNot(loaded, "");
|
||||
} else {
|
||||
return operand;
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4784,12 +4785,16 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const optional_ty = self.air.typeOf(ty_op.operand).childType();
|
||||
const result_ty = self.air.getRefType(ty_op.ty);
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
const payload_ty = optional_ty.optionalChild(&buf);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
// We have a pointer to a zero-bit value and we need to return
|
||||
// a pointer to a zero-bit value.
|
||||
return operand;
|
||||
|
||||
// TODO once we update to LLVM 14 this bitcast won't be necessary.
|
||||
const res_ptr_ty = try self.dg.llvmType(result_ty);
|
||||
return self.builder.buildBitCast(operand, res_ptr_ty, "");
|
||||
}
|
||||
if (optional_ty.isPtrLikeOptional()) {
|
||||
// The payload and the optional are the same value.
|
||||
@ -4807,13 +4812,17 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const optional_ty = self.air.typeOf(ty_op.operand).childType();
|
||||
const result_ty = self.air.getRefType(ty_op.ty);
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
const payload_ty = optional_ty.optionalChild(&buf);
|
||||
const non_null_bit = self.context.intType(1).constAllOnes();
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
// We have a pointer to a i1. We need to set it to 1 and then return the same pointer.
|
||||
_ = self.builder.buildStore(non_null_bit, operand);
|
||||
return operand;
|
||||
|
||||
// TODO once we update to LLVM 14 this bitcast won't be necessary.
|
||||
const res_ptr_ty = try self.dg.llvmType(result_ty);
|
||||
return self.builder.buildBitCast(operand, res_ptr_ty, "");
|
||||
}
|
||||
if (optional_ty.isPtrLikeOptional()) {
|
||||
// The payload and the optional are the same value.
|
||||
@ -4872,7 +4881,13 @@ pub const FuncGen = struct {
|
||||
const target = self.dg.module.getTarget();
|
||||
const offset: u8 = if (payload_ty.abiAlignment(target) > Type.anyerror.abiSize(target)) 2 else 1;
|
||||
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null;
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
if (!operand_is_ptr) return null;
|
||||
|
||||
// TODO once we update to LLVM 14 this bitcast won't be necessary.
|
||||
const res_ptr_ty = try self.dg.llvmType(result_ty);
|
||||
return self.builder.buildBitCast(operand, res_ptr_ty, "");
|
||||
}
|
||||
if (operand_is_ptr or isByRef(payload_ty)) {
|
||||
return self.builder.buildStructGEP(operand, offset, "");
|
||||
}
|
||||
@ -7205,7 +7220,7 @@ pub const FuncGen = struct {
|
||||
return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, "");
|
||||
}
|
||||
|
||||
fn getIntrinsic(self: *FuncGen, name: []const u8, types: []*const llvm.Type) *const llvm.Value {
|
||||
fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value {
|
||||
const id = llvm.lookupIntrinsicID(name.ptr, name.len);
|
||||
assert(id != 0);
|
||||
return self.llvmModule().getIntrinsicDeclaration(id, types.ptr, types.len);
|
||||
|
||||
@ -60,7 +60,7 @@ pub const Context = opaque {
|
||||
Packed: Bool,
|
||||
) *const Type;
|
||||
|
||||
const structCreateNamed = LLVMStructCreateNamed;
|
||||
pub const structCreateNamed = LLVMStructCreateNamed;
|
||||
extern fn LLVMStructCreateNamed(C: *const Context, Name: [*:0]const u8) *const Type;
|
||||
|
||||
pub const constString = LLVMConstStringInContext;
|
||||
@ -320,7 +320,7 @@ pub const Module = opaque {
|
||||
extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;
|
||||
|
||||
pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration;
|
||||
extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]*const Type, ParamCount: usize) *const Value;
|
||||
extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]const *const Type, ParamCount: usize) *const Value;
|
||||
|
||||
pub const printToString = LLVMPrintModuleToString;
|
||||
extern fn LLVMPrintModuleToString(*const Module) [*:0]const u8;
|
||||
|
||||
@ -368,11 +368,13 @@ pub fn translate(
|
||||
resources_path: [*:0]const u8,
|
||||
zig_is_stage1: bool,
|
||||
) !std.zig.Ast {
|
||||
// TODO stage2 bug
|
||||
var tmp = errors;
|
||||
const ast_unit = clang.LoadFromCommandLine(
|
||||
args_begin,
|
||||
args_end,
|
||||
&errors.ptr,
|
||||
&errors.len,
|
||||
&tmp.ptr,
|
||||
&tmp.len,
|
||||
resources_path,
|
||||
) orelse {
|
||||
if (errors.len == 0) return error.ASTUnitFailure;
|
||||
@ -5325,7 +5327,7 @@ const MacroCtx = struct {
|
||||
try self.fail(
|
||||
c,
|
||||
"unable to translate C expr: expected '{s}' instead got '{s}'",
|
||||
.{ CToken.Id.symbol(expected_id), next_id.symbol() },
|
||||
.{ CToken.Id.symbolName(expected_id), next_id.symbol() },
|
||||
);
|
||||
return error.ParseError;
|
||||
}
|
||||
|
||||
@ -779,7 +779,7 @@ const TokenTag = std.zig.Token.Tag;
|
||||
|
||||
const Context = struct {
|
||||
gpa: Allocator,
|
||||
buf: std.ArrayList(u8) = .{},
|
||||
buf: std.ArrayList(u8),
|
||||
nodes: std.zig.Ast.NodeList = .{},
|
||||
extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{},
|
||||
tokens: std.zig.Ast.TokenList = .{},
|
||||
|
||||
@ -2706,6 +2706,11 @@ double ZigClangFloatingLiteral_getValueAsApproximateDouble(const ZigClangFloatin
|
||||
return casted->getValueAsApproximateDouble();
|
||||
}
|
||||
|
||||
struct ZigClangSourceLocation ZigClangFloatingLiteral_getBeginLoc(const struct ZigClangFloatingLiteral *self) {
|
||||
auto casted = reinterpret_cast<const clang::FloatingLiteral *>(self);
|
||||
return bitcast(casted->getBeginLoc());
|
||||
}
|
||||
|
||||
ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigClangFloatingLiteral *self) {
|
||||
auto casted = reinterpret_cast<const clang::FloatingLiteral *>(self);
|
||||
return static_cast<ZigClangAPFloatBase_Semantics>(casted->getRawSemantics());
|
||||
|
||||
@ -1245,6 +1245,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDeclStmt_getBeginLoc(const st
|
||||
ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST,
|
||||
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM);
|
||||
ZIG_EXTERN_C double ZigClangFloatingLiteral_getValueAsApproximateDouble(const ZigClangFloatingLiteral *self);
|
||||
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFloatingLiteral_getBeginLoc(const struct ZigClangFloatingLiteral *);
|
||||
ZIG_EXTERN_C ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigClangFloatingLiteral *self);
|
||||
|
||||
ZIG_EXTERN_C enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self);
|
||||
|
||||
@ -332,3 +332,42 @@ test "array of optional unaligned types" {
|
||||
i += 1;
|
||||
try expect(Enum.three == values[i].?.Num);
|
||||
}
|
||||
|
||||
test "optional pointer to zero bit optional payload" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
const B = struct {
|
||||
fn foo(_: *@This()) void {}
|
||||
};
|
||||
const A = struct {
|
||||
b: ?B = .{},
|
||||
};
|
||||
var a: A = .{};
|
||||
var a_ptr = &a;
|
||||
if (a_ptr.b) |*some| {
|
||||
some.foo();
|
||||
}
|
||||
}
|
||||
|
||||
test "optional pointer to zero bit error union payload" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
const B = struct {
|
||||
fn foo(_: *@This()) void {}
|
||||
};
|
||||
const A = struct {
|
||||
b: anyerror!B = .{},
|
||||
};
|
||||
var a: A = .{};
|
||||
var a_ptr = &a;
|
||||
if (a_ptr.b) |*some| {
|
||||
some.foo();
|
||||
} else |_| {}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user