mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
commit
5269cbea20
@ -7082,7 +7082,7 @@ fn builtinCall(
|
||||
.bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),
|
||||
.TypeOf => return typeOf( gz, scope, rl, node, params),
|
||||
.union_init => return unionInit(gz, scope, rl, node, params),
|
||||
.c_import => return cImport( gz, scope, rl, node, params[0]),
|
||||
.c_import => return cImport( gz, scope, node, params[0]),
|
||||
|
||||
.@"export" => {
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
@ -7269,6 +7269,7 @@ fn builtinCall(
|
||||
return rvalue(gz, rl, result, node);
|
||||
},
|
||||
.c_define => {
|
||||
if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
|
||||
const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]);
|
||||
const value = try comptimeExpr(gz, scope, .none, params[1]);
|
||||
const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
|
||||
@ -7641,6 +7642,8 @@ fn simpleCBuiltin(
|
||||
operand_node: Ast.Node.Index,
|
||||
tag: Zir.Inst.Extended,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
|
||||
if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
|
||||
const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node);
|
||||
_ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
@ -7689,7 +7692,6 @@ fn shiftOp(
|
||||
fn cImport(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
node: Ast.Node.Index,
|
||||
body_node: Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
@ -7698,6 +7700,7 @@ fn cImport(
|
||||
|
||||
var block_scope = gz.makeSubBlock(scope);
|
||||
block_scope.force_comptime = true;
|
||||
block_scope.c_import = true;
|
||||
defer block_scope.instructions.deinit(gpa);
|
||||
|
||||
const block_inst = try gz.addBlock(.c_import, node);
|
||||
@ -7708,7 +7711,7 @@ fn cImport(
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
try gz.instructions.append(gpa, block_inst);
|
||||
|
||||
return rvalue(gz, rl, .void_value, node);
|
||||
return indexToRef(block_inst);
|
||||
}
|
||||
|
||||
fn overflowArithmetic(
|
||||
@ -9025,6 +9028,7 @@ const GenZir = struct {
|
||||
base: Scope = Scope{ .tag = base_tag },
|
||||
force_comptime: bool,
|
||||
in_defer: bool,
|
||||
c_import: bool = false,
|
||||
/// How decls created in this scope should be named.
|
||||
anon_name_strategy: Zir.Inst.NameStrategy = .anon,
|
||||
/// The containing decl AST node.
|
||||
@ -9070,6 +9074,7 @@ const GenZir = struct {
|
||||
return .{
|
||||
.force_comptime = gz.force_comptime,
|
||||
.in_defer = gz.in_defer,
|
||||
.c_import = gz.c_import,
|
||||
.decl_node_index = gz.decl_node_index,
|
||||
.decl_line = gz.decl_line,
|
||||
.parent = scope,
|
||||
|
||||
@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
|
||||
|
||||
const dep_basename = std.fs.path.basename(out_dep_path);
|
||||
try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
|
||||
try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
|
||||
if (build_options.is_stage1 and comp.bin_file.options.use_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
|
||||
|
||||
const digest = man.final();
|
||||
const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
|
||||
@ -1325,6 +1325,8 @@ pub const Scope = struct {
|
||||
/// when null, it is determined by build mode, changed by @setRuntimeSafety
|
||||
want_safety: ?bool = null,
|
||||
|
||||
c_import_buf: ?*std.ArrayList(u8) = null,
|
||||
|
||||
const Param = struct {
|
||||
/// `noreturn` means `anytype`.
|
||||
ty: Type,
|
||||
@ -1377,6 +1379,7 @@ pub const Scope = struct {
|
||||
.runtime_loop = parent.runtime_loop,
|
||||
.runtime_index = parent.runtime_index,
|
||||
.want_safety = parent.want_safety,
|
||||
.c_import_buf = parent.c_import_buf,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
295
src/Sema.zig
295
src/Sema.zig
@ -83,6 +83,7 @@ const Decl = Module.Decl;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
const RangeSet = @import("RangeSet.zig");
|
||||
const target_util = @import("target.zig");
|
||||
const Package = @import("Package.zig");
|
||||
|
||||
pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref);
|
||||
|
||||
@ -2138,10 +2139,77 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = pl_node.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
|
||||
const body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
|
||||
return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirCImport", .{});
|
||||
// we check this here to avoid undefined symbols
|
||||
if (!@import("build_options").have_llvm)
|
||||
return sema.mod.fail(&parent_block.base, src, "cannot do C import on Zig compiler not built with LLVM-extension", .{});
|
||||
|
||||
var c_import_buf = std.ArrayList(u8).init(sema.gpa);
|
||||
defer c_import_buf.deinit();
|
||||
|
||||
var child_block: Scope.Block = .{
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.src_decl = parent_block.src_decl,
|
||||
.instructions = .{},
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.c_import_buf = &c_import_buf,
|
||||
};
|
||||
defer child_block.instructions.deinit(sema.gpa);
|
||||
|
||||
_ = try sema.analyzeBody(&child_block, body);
|
||||
|
||||
const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err|
|
||||
return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
|
||||
|
||||
if (c_import_res.errors.len != 0) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.mod.errMsg(&child_block.base, src, "C import failed", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
if (!sema.mod.comp.bin_file.options.link_libc)
|
||||
try sema.mod.errNote(&child_block.base, src, msg, "libc headers not available; compilation does not link against libc", .{});
|
||||
|
||||
for (c_import_res.errors) |_| {
|
||||
// TODO integrate with LazySrcLoc
|
||||
// try sema.mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]});
|
||||
// if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
|
||||
// clang_err.line + 1,
|
||||
// clang_err.column + 1,
|
||||
}
|
||||
@import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg);
|
||||
}
|
||||
const c_import_pkg = Package.create(
|
||||
sema.gpa,
|
||||
null,
|
||||
c_import_res.out_zig_path,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => unreachable, // we pass null for root_src_dir_path
|
||||
};
|
||||
const std_pkg = sema.mod.main_pkg.table.get("std").?;
|
||||
const builtin_pkg = sema.mod.main_pkg.table.get("builtin").?;
|
||||
try c_import_pkg.add(sema.gpa, "builtin", builtin_pkg);
|
||||
try c_import_pkg.add(sema.gpa, "std", std_pkg);
|
||||
|
||||
const result = sema.mod.importPkg(c_import_pkg) catch |err|
|
||||
return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
|
||||
|
||||
sema.mod.astGenFile(result.file) catch |err|
|
||||
return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
|
||||
|
||||
try sema.mod.semaFile(result.file);
|
||||
const file_root_decl = result.file.root_decl.?;
|
||||
try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl);
|
||||
return sema.addType(file_root_decl.ty);
|
||||
}
|
||||
|
||||
fn zirSuspendBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -6405,10 +6473,41 @@ fn runtimeBoolCmp(
|
||||
|
||||
fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
|
||||
const target = sema.mod.getTarget();
|
||||
const abi_size = operand_ty.abiSize(target);
|
||||
const abi_size = switch (operand_ty.zigTypeTag()) {
|
||||
.Fn => unreachable,
|
||||
.NoReturn,
|
||||
.Undefined,
|
||||
.Null,
|
||||
.BoundFn,
|
||||
.Opaque,
|
||||
=> return sema.mod.fail(&block.base, src, "no size available for type '{}'", .{operand_ty}),
|
||||
.Type,
|
||||
.EnumLiteral,
|
||||
.ComptimeFloat,
|
||||
.ComptimeInt,
|
||||
.Void,
|
||||
=> 0,
|
||||
|
||||
.Bool,
|
||||
.Int,
|
||||
.Float,
|
||||
.Pointer,
|
||||
.Array,
|
||||
.Struct,
|
||||
.Optional,
|
||||
.ErrorUnion,
|
||||
.ErrorSet,
|
||||
.Enum,
|
||||
.Union,
|
||||
.Vector,
|
||||
.Frame,
|
||||
.AnyFrame,
|
||||
=> operand_ty.abiSize(target),
|
||||
};
|
||||
return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size);
|
||||
}
|
||||
|
||||
@ -6456,19 +6555,80 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Type => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Type)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.Void => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Void)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.Bool => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Bool)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.NoReturn => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.NoReturn)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.ComptimeFloat => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeFloat)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.ComptimeInt => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeInt)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.Undefined => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Undefined)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.Null => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Null)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.EnumLiteral => return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.EnumLiteral)),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
),
|
||||
.Fn => {
|
||||
const info = ty.fnInfo();
|
||||
const field_values = try sema.arena.alloc(Value, 6);
|
||||
// calling_convention: CallingConvention,
|
||||
field_values[0] = try Value.Tag.enum_field_index.create(
|
||||
sema.arena,
|
||||
@enumToInt(ty.fnCallingConvention()),
|
||||
);
|
||||
field_values[0] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc));
|
||||
// alignment: comptime_int,
|
||||
field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target));
|
||||
// is_generic: bool,
|
||||
field_values[2] = Value.initTag(.bool_false); // TODO
|
||||
field_values[2] = if (info.is_generic) Value.initTag(.bool_true) else Value.initTag(.bool_false);
|
||||
// is_var_args: bool,
|
||||
field_values[3] = Value.initTag(.bool_false); // TODO
|
||||
field_values[3] = if (info.is_var_args) Value.initTag(.bool_true) else Value.initTag(.bool_false);
|
||||
// return_type: ?type,
|
||||
field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
|
||||
// args: []const FnArg,
|
||||
@ -6477,10 +6637,7 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(
|
||||
sema.arena,
|
||||
@enumToInt(@typeInfo(std.builtin.TypeInfo).Union.tag_type.?.Fn),
|
||||
),
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Fn)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
@ -6499,10 +6656,92 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(
|
||||
sema.arena,
|
||||
@enumToInt(@typeInfo(std.builtin.TypeInfo).Union.tag_type.?.Int),
|
||||
),
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Int)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
},
|
||||
.Float => {
|
||||
const field_values = try sema.arena.alloc(Value, 1);
|
||||
// bits: comptime_int,
|
||||
field_values[0] = try Value.Tag.int_u64.create(sema.arena, ty.bitSize(target));
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Float)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
},
|
||||
.Pointer => {
|
||||
const info = ty.ptrInfo().data;
|
||||
const field_values = try sema.arena.alloc(Value, 7);
|
||||
// size: Size,
|
||||
field_values[0] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.size));
|
||||
// is_const: bool,
|
||||
field_values[1] = if (!info.mutable) Value.initTag(.bool_true) else Value.initTag(.bool_false);
|
||||
// is_volatile: bool,
|
||||
field_values[2] = if (info.@"volatile") Value.initTag(.bool_true) else Value.initTag(.bool_false);
|
||||
// alignment: comptime_int,
|
||||
field_values[3] = try Value.Tag.int_u64.create(sema.arena, info.@"align");
|
||||
// child: type,
|
||||
field_values[4] = try Value.Tag.ty.create(sema.arena, info.pointee_type);
|
||||
// is_allowzero: bool,
|
||||
field_values[5] = if (info.@"allowzero") Value.initTag(.bool_true) else Value.initTag(.bool_false);
|
||||
// sentinel: anytype,
|
||||
field_values[6] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Pointer)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
},
|
||||
.Array => {
|
||||
const info = ty.arrayInfo();
|
||||
const field_values = try sema.arena.alloc(Value, 3);
|
||||
// len: comptime_int,
|
||||
field_values[0] = try Value.Tag.int_u64.create(sema.arena, info.len);
|
||||
// child: type,
|
||||
field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);
|
||||
// sentinel: anytype,
|
||||
field_values[2] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Array)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
},
|
||||
.Optional => {
|
||||
const field_values = try sema.arena.alloc(Value, 1);
|
||||
// child: type,
|
||||
field_values[0] = try Value.Tag.ty.create(sema.arena, try ty.optionalChildAlloc(sema.arena));
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Optional)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const field_values = try sema.arena.alloc(Value, 2);
|
||||
// error_set: type,
|
||||
field_values[0] = try Value.Tag.ty.create(sema.arena, ty.errorUnionSet());
|
||||
// payload: type,
|
||||
field_values[1] = try Value.Tag.ty.create(sema.arena, ty.errorUnionPayload());
|
||||
|
||||
return sema.addConstant(
|
||||
type_info_ty,
|
||||
try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorUnion)),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values),
|
||||
}),
|
||||
);
|
||||
@ -8226,7 +8465,10 @@ fn zirCUndef(
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.node };
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCUndef", .{});
|
||||
|
||||
const name = try sema.resolveConstString(block, src, extra.operand);
|
||||
try block.c_import_buf.?.writer().print("#undefine {s}\n", .{name});
|
||||
return Air.Inst.Ref.void_value;
|
||||
}
|
||||
|
||||
fn zirCInclude(
|
||||
@ -8236,7 +8478,10 @@ fn zirCInclude(
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.node };
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCInclude", .{});
|
||||
|
||||
const name = try sema.resolveConstString(block, src, extra.operand);
|
||||
try block.c_import_buf.?.writer().print("#include <{s}>\n", .{name});
|
||||
return Air.Inst.Ref.void_value;
|
||||
}
|
||||
|
||||
fn zirCDefine(
|
||||
@ -8246,7 +8491,15 @@ fn zirCDefine(
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.node };
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCDefine", .{});
|
||||
|
||||
const name = try sema.resolveConstString(block, src, extra.lhs);
|
||||
if (sema.typeOf(extra.rhs).zigTypeTag() != .Void) {
|
||||
const value = try sema.resolveConstString(block, src, extra.rhs);
|
||||
try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });
|
||||
} else {
|
||||
try block.c_import_buf.?.writer().print("#define {s}\n", .{name});
|
||||
}
|
||||
return Air.Inst.Ref.void_value;
|
||||
}
|
||||
|
||||
fn zirWasmMemorySize(
|
||||
|
||||
@ -407,15 +407,27 @@ const Writer = struct {
|
||||
.mul_with_saturation,
|
||||
.shl_with_saturation,
|
||||
=> try self.writeSaturatingArithmetic(stream, extended),
|
||||
|
||||
.struct_decl => try self.writeStructDecl(stream, extended),
|
||||
.union_decl => try self.writeUnionDecl(stream, extended),
|
||||
.enum_decl => try self.writeEnumDecl(stream, extended),
|
||||
|
||||
.c_undef, .c_include => {
|
||||
const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
try self.writeInstRef(stream, inst_data.operand);
|
||||
try stream.writeAll(") ");
|
||||
},
|
||||
|
||||
.c_define => {
|
||||
const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||
try self.writeInstRef(stream, inst_data.lhs);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, inst_data.rhs);
|
||||
try stream.writeByte(')');
|
||||
},
|
||||
|
||||
.alloc,
|
||||
.builtin_extern,
|
||||
.c_undef,
|
||||
.c_include,
|
||||
.c_define,
|
||||
.wasm_memory_size,
|
||||
.wasm_memory_grow,
|
||||
=> try stream.writeAll("TODO))"),
|
||||
|
||||
@ -602,8 +602,8 @@ pub const Type = extern union {
|
||||
}
|
||||
return false;
|
||||
},
|
||||
.Float => return a.tag() == b.tag(),
|
||||
.Opaque,
|
||||
.Float,
|
||||
.BoundFn,
|
||||
.Frame,
|
||||
=> std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
|
||||
|
||||
@ -11,6 +11,8 @@ test {
|
||||
_ = @import("behavior/array.zig");
|
||||
_ = @import("behavior/usingnamespace.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof.zig");
|
||||
_ = @import("behavior/translate_c_macros.zig");
|
||||
|
||||
if (builtin.zig_is_stage2) {
|
||||
// When all comptime_memory.zig tests pass, #9646 can be closed.
|
||||
@ -128,7 +130,7 @@ test {
|
||||
_ = @import("behavior/saturating_arithmetic.zig");
|
||||
_ = @import("behavior/shuffle.zig");
|
||||
_ = @import("behavior/select.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof_stage1.zig");
|
||||
_ = @import("behavior/slice.zig");
|
||||
_ = @import("behavior/slice_sentinel_comptime.zig");
|
||||
_ = @import("behavior/struct.zig");
|
||||
@ -157,6 +159,6 @@ test {
|
||||
_ = @import("behavior/while.zig");
|
||||
_ = @import("behavior/widening.zig");
|
||||
_ = @import("behavior/src.zig");
|
||||
_ = @import("behavior/translate_c_macros.zig");
|
||||
_ = @import("behavior/translate_c_macros_stage1.zig");
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,118 +10,6 @@ test "@sizeOf and @TypeOf" {
|
||||
const x: u16 = 13;
|
||||
const z: @TypeOf(x) = 19;
|
||||
|
||||
const A = struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
h: u9,
|
||||
i: u7,
|
||||
};
|
||||
|
||||
const P = packed struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
h: u9,
|
||||
i: u7,
|
||||
};
|
||||
|
||||
test "@offsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
try expect(@offsetOf(P, "a") == 0);
|
||||
try expect(@offsetOf(P, "b") == 1);
|
||||
try expect(@offsetOf(P, "c") == 5);
|
||||
try expect(@offsetOf(P, "d") == 6);
|
||||
try expect(@offsetOf(P, "e") == 6);
|
||||
try expect(@offsetOf(P, "f") == 7);
|
||||
try expect(@offsetOf(P, "g") == 9);
|
||||
try expect(@offsetOf(P, "h") == 11);
|
||||
try expect(@offsetOf(P, "i") == 12);
|
||||
|
||||
// Normal struct fields can be moved/padded
|
||||
var a: A = undefined;
|
||||
try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a"));
|
||||
try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b"));
|
||||
try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c"));
|
||||
try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d"));
|
||||
try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e"));
|
||||
try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f"));
|
||||
try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g"));
|
||||
try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h"));
|
||||
try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i"));
|
||||
}
|
||||
|
||||
test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
|
||||
const p3a_len = 3;
|
||||
const P3 = packed struct {
|
||||
a: [p3a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P3, "a"));
|
||||
try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b"));
|
||||
|
||||
const p5a_len = 5;
|
||||
const P5 = packed struct {
|
||||
a: [p5a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P5, "a"));
|
||||
try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b"));
|
||||
|
||||
const p6a_len = 6;
|
||||
const P6 = packed struct {
|
||||
a: [p6a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P6, "a"));
|
||||
try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b"));
|
||||
|
||||
const p7a_len = 7;
|
||||
const P7 = packed struct {
|
||||
a: [p7a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P7, "a"));
|
||||
try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b"));
|
||||
|
||||
const p9a_len = 9;
|
||||
const P9 = packed struct {
|
||||
a: [p9a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P9, "a"));
|
||||
try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b"));
|
||||
|
||||
// 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
|
||||
}
|
||||
|
||||
test "@bitOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
try expect(@bitOffsetOf(P, "a") == 0);
|
||||
try expect(@bitOffsetOf(P, "b") == 8);
|
||||
try expect(@bitOffsetOf(P, "c") == 40);
|
||||
try expect(@bitOffsetOf(P, "d") == 48);
|
||||
try expect(@bitOffsetOf(P, "e") == 51);
|
||||
try expect(@bitOffsetOf(P, "f") == 56);
|
||||
try expect(@bitOffsetOf(P, "g") == 72);
|
||||
|
||||
try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
|
||||
try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
|
||||
try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
|
||||
try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
|
||||
try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
|
||||
try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
|
||||
try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
|
||||
}
|
||||
|
||||
test "@sizeOf on compile-time types" {
|
||||
try expect(@sizeOf(comptime_int) == 0);
|
||||
try expect(@sizeOf(comptime_float) == 0);
|
||||
@ -129,34 +17,6 @@ test "@sizeOf on compile-time types" {
|
||||
try expect(@sizeOf(@TypeOf(type)) == 0);
|
||||
}
|
||||
|
||||
test "@sizeOf(T) == 0 doesn't force resolving struct size" {
|
||||
const S = struct {
|
||||
const Foo = struct {
|
||||
y: if (@sizeOf(Foo) == 0) u64 else u32,
|
||||
};
|
||||
const Bar = struct {
|
||||
x: i32,
|
||||
y: if (0 == @sizeOf(Bar)) u64 else u32,
|
||||
};
|
||||
};
|
||||
|
||||
try expect(@sizeOf(S.Foo) == 4);
|
||||
try expect(@sizeOf(S.Bar) == 8);
|
||||
}
|
||||
|
||||
test "@TypeOf() has no runtime side effects" {
|
||||
const S = struct {
|
||||
fn foo(comptime T: type, ptr: *T) T {
|
||||
ptr.* += 1;
|
||||
return ptr.*;
|
||||
}
|
||||
};
|
||||
var data: i32 = 0;
|
||||
const T = @TypeOf(S.foo(i32, &data));
|
||||
comptime try expect(T == i32);
|
||||
try expect(data == 0);
|
||||
}
|
||||
|
||||
test "@TypeOf() with multiple arguments" {
|
||||
{
|
||||
var var_1: u32 = undefined;
|
||||
@ -180,19 +40,6 @@ test "@TypeOf() with multiple arguments" {
|
||||
}
|
||||
}
|
||||
|
||||
test "branching logic inside @TypeOf" {
|
||||
const S = struct {
|
||||
var data: i32 = 0;
|
||||
fn foo() anyerror!i32 {
|
||||
data += 1;
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
const T = @TypeOf(S.foo() catch undefined);
|
||||
comptime try expect(T == i32);
|
||||
try expect(S.data == 0);
|
||||
}
|
||||
|
||||
fn fn1(alpha: bool) void {
|
||||
const n: usize = 7;
|
||||
_ = if (alpha) n else @sizeOf(usize);
|
||||
@ -201,64 +48,3 @@ fn fn1(alpha: bool) void {
|
||||
test "lazy @sizeOf result is checked for definedness" {
|
||||
_ = fn1;
|
||||
}
|
||||
|
||||
test "@bitSizeOf" {
|
||||
try expect(@bitSizeOf(u2) == 2);
|
||||
try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
|
||||
try expect(@bitSizeOf(struct {
|
||||
a: u2,
|
||||
}) == 8);
|
||||
try expect(@bitSizeOf(packed struct {
|
||||
a: u2,
|
||||
}) == 2);
|
||||
}
|
||||
|
||||
test "@sizeOf comparison against zero" {
|
||||
const S0 = struct {
|
||||
f: *@This(),
|
||||
};
|
||||
const U0 = union {
|
||||
f: *@This(),
|
||||
};
|
||||
const S1 = struct {
|
||||
fn H(comptime T: type) type {
|
||||
return struct {
|
||||
x: T,
|
||||
};
|
||||
}
|
||||
f0: H(*@This()),
|
||||
f1: H(**@This()),
|
||||
f2: H(***@This()),
|
||||
};
|
||||
const U1 = union {
|
||||
fn H(comptime T: type) type {
|
||||
return struct {
|
||||
x: T,
|
||||
};
|
||||
}
|
||||
f0: H(*@This()),
|
||||
f1: H(**@This()),
|
||||
f2: H(***@This()),
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest(comptime T: type, comptime result: bool) !void {
|
||||
try expectEqual(result, @sizeOf(T) > 0);
|
||||
}
|
||||
};
|
||||
// Zero-sized type
|
||||
try S.doTheTest(u0, false);
|
||||
try S.doTheTest(*u0, false);
|
||||
// Non byte-sized type
|
||||
try S.doTheTest(u1, true);
|
||||
try S.doTheTest(*u1, true);
|
||||
// Regular type
|
||||
try S.doTheTest(u8, true);
|
||||
try S.doTheTest(*u8, true);
|
||||
try S.doTheTest(f32, true);
|
||||
try S.doTheTest(*f32, true);
|
||||
// Container with ptr pointing to themselves
|
||||
try S.doTheTest(S0, true);
|
||||
try S.doTheTest(U0, true);
|
||||
try S.doTheTest(S1, true);
|
||||
try S.doTheTest(U1, true);
|
||||
}
|
||||
|
||||
218
test/behavior/sizeof_and_typeof_stage1.zig
Normal file
218
test/behavior/sizeof_and_typeof_stage1.zig
Normal file
@ -0,0 +1,218 @@
|
||||
const std = @import("std");
|
||||
const builtin = std.builtin;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
const A = struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
h: u9,
|
||||
i: u7,
|
||||
};
|
||||
|
||||
const P = packed struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
h: u9,
|
||||
i: u7,
|
||||
};
|
||||
|
||||
test "@offsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
try expect(@offsetOf(P, "a") == 0);
|
||||
try expect(@offsetOf(P, "b") == 1);
|
||||
try expect(@offsetOf(P, "c") == 5);
|
||||
try expect(@offsetOf(P, "d") == 6);
|
||||
try expect(@offsetOf(P, "e") == 6);
|
||||
try expect(@offsetOf(P, "f") == 7);
|
||||
try expect(@offsetOf(P, "g") == 9);
|
||||
try expect(@offsetOf(P, "h") == 11);
|
||||
try expect(@offsetOf(P, "i") == 12);
|
||||
|
||||
// Normal struct fields can be moved/padded
|
||||
var a: A = undefined;
|
||||
try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a"));
|
||||
try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b"));
|
||||
try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c"));
|
||||
try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d"));
|
||||
try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e"));
|
||||
try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f"));
|
||||
try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g"));
|
||||
try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h"));
|
||||
try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i"));
|
||||
}
|
||||
|
||||
test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
|
||||
const p3a_len = 3;
|
||||
const P3 = packed struct {
|
||||
a: [p3a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P3, "a"));
|
||||
try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b"));
|
||||
|
||||
const p5a_len = 5;
|
||||
const P5 = packed struct {
|
||||
a: [p5a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P5, "a"));
|
||||
try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b"));
|
||||
|
||||
const p6a_len = 6;
|
||||
const P6 = packed struct {
|
||||
a: [p6a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P6, "a"));
|
||||
try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b"));
|
||||
|
||||
const p7a_len = 7;
|
||||
const P7 = packed struct {
|
||||
a: [p7a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P7, "a"));
|
||||
try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b"));
|
||||
|
||||
const p9a_len = 9;
|
||||
const P9 = packed struct {
|
||||
a: [p9a_len]u8,
|
||||
b: usize,
|
||||
};
|
||||
try std.testing.expectEqual(0, @offsetOf(P9, "a"));
|
||||
try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b"));
|
||||
|
||||
// 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
|
||||
}
|
||||
|
||||
test "@bitOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
try expect(@bitOffsetOf(P, "a") == 0);
|
||||
try expect(@bitOffsetOf(P, "b") == 8);
|
||||
try expect(@bitOffsetOf(P, "c") == 40);
|
||||
try expect(@bitOffsetOf(P, "d") == 48);
|
||||
try expect(@bitOffsetOf(P, "e") == 51);
|
||||
try expect(@bitOffsetOf(P, "f") == 56);
|
||||
try expect(@bitOffsetOf(P, "g") == 72);
|
||||
|
||||
try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
|
||||
try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
|
||||
try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
|
||||
try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
|
||||
try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
|
||||
try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
|
||||
try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
|
||||
}
|
||||
|
||||
test "@sizeOf(T) == 0 doesn't force resolving struct size" {
|
||||
const S = struct {
|
||||
const Foo = struct {
|
||||
y: if (@sizeOf(Foo) == 0) u64 else u32,
|
||||
};
|
||||
const Bar = struct {
|
||||
x: i32,
|
||||
y: if (0 == @sizeOf(Bar)) u64 else u32,
|
||||
};
|
||||
};
|
||||
|
||||
try expect(@sizeOf(S.Foo) == 4);
|
||||
try expect(@sizeOf(S.Bar) == 8);
|
||||
}
|
||||
|
||||
test "@TypeOf() has no runtime side effects" {
|
||||
const S = struct {
|
||||
fn foo(comptime T: type, ptr: *T) T {
|
||||
ptr.* += 1;
|
||||
return ptr.*;
|
||||
}
|
||||
};
|
||||
var data: i32 = 0;
|
||||
const T = @TypeOf(S.foo(i32, &data));
|
||||
comptime try expect(T == i32);
|
||||
try expect(data == 0);
|
||||
}
|
||||
|
||||
test "branching logic inside @TypeOf" {
|
||||
const S = struct {
|
||||
var data: i32 = 0;
|
||||
fn foo() anyerror!i32 {
|
||||
data += 1;
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
const T = @TypeOf(S.foo() catch undefined);
|
||||
comptime try expect(T == i32);
|
||||
try expect(S.data == 0);
|
||||
}
|
||||
|
||||
test "@bitSizeOf" {
|
||||
try expect(@bitSizeOf(u2) == 2);
|
||||
try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
|
||||
try expect(@bitSizeOf(struct {
|
||||
a: u2,
|
||||
}) == 8);
|
||||
try expect(@bitSizeOf(packed struct {
|
||||
a: u2,
|
||||
}) == 2);
|
||||
}
|
||||
|
||||
test "@sizeOf comparison against zero" {
|
||||
const S0 = struct {
|
||||
f: *@This(),
|
||||
};
|
||||
const U0 = union {
|
||||
f: *@This(),
|
||||
};
|
||||
const S1 = struct {
|
||||
fn H(comptime T: type) type {
|
||||
return struct {
|
||||
x: T,
|
||||
};
|
||||
}
|
||||
f0: H(*@This()),
|
||||
f1: H(**@This()),
|
||||
f2: H(***@This()),
|
||||
};
|
||||
const U1 = union {
|
||||
fn H(comptime T: type) type {
|
||||
return struct {
|
||||
x: T,
|
||||
};
|
||||
}
|
||||
f0: H(*@This()),
|
||||
f1: H(**@This()),
|
||||
f2: H(***@This()),
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest(comptime T: type, comptime result: bool) !void {
|
||||
try expectEqual(result, @sizeOf(T) > 0);
|
||||
}
|
||||
};
|
||||
// Zero-sized type
|
||||
try S.doTheTest(u0, false);
|
||||
try S.doTheTest(*u0, false);
|
||||
// Non byte-sized type
|
||||
try S.doTheTest(u1, true);
|
||||
try S.doTheTest(*u1, true);
|
||||
// Regular type
|
||||
try S.doTheTest(u8, true);
|
||||
try S.doTheTest(*u8, true);
|
||||
try S.doTheTest(f32, true);
|
||||
try S.doTheTest(*f32, true);
|
||||
// Container with ptr pointing to themselves
|
||||
try S.doTheTest(S0, true);
|
||||
try S.doTheTest(U0, true);
|
||||
try S.doTheTest(S1, true);
|
||||
try S.doTheTest(U1, true);
|
||||
}
|
||||
@ -3,28 +3,6 @@ const expectEqual = @import("std").testing.expectEqual;
|
||||
|
||||
const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
|
||||
|
||||
test "initializer list expression" {
|
||||
try expectEqual(h.Color{
|
||||
.r = 200,
|
||||
.g = 200,
|
||||
.b = 200,
|
||||
.a = 255,
|
||||
}, h.LIGHTGRAY);
|
||||
}
|
||||
|
||||
test "sizeof in macros" {
|
||||
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
|
||||
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
|
||||
}
|
||||
|
||||
test "reference to a struct type" {
|
||||
try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
|
||||
}
|
||||
|
||||
test "cast negative integer to pointer" {
|
||||
try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
|
||||
}
|
||||
|
||||
test "casting to void with a macro" {
|
||||
h.IGNORE_ME_1(42);
|
||||
h.IGNORE_ME_2(42);
|
||||
|
||||
26
test/behavior/translate_c_macros_stage1.zig
Normal file
26
test/behavior/translate_c_macros_stage1.zig
Normal file
@ -0,0 +1,26 @@
|
||||
const expect = @import("std").testing.expect;
|
||||
const expectEqual = @import("std").testing.expectEqual;
|
||||
|
||||
const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
|
||||
|
||||
test "initializer list expression" {
|
||||
try expectEqual(h.Color{
|
||||
.r = 200,
|
||||
.g = 200,
|
||||
.b = 200,
|
||||
.a = 255,
|
||||
}, h.LIGHTGRAY);
|
||||
}
|
||||
|
||||
test "sizeof in macros" {
|
||||
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
|
||||
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
|
||||
}
|
||||
|
||||
test "reference to a struct type" {
|
||||
try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
|
||||
}
|
||||
|
||||
test "cast negative integer to pointer" {
|
||||
try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user