Zenコンパイラに組み込まれている型や列挙型の情報です。Zenのプログラム内では、builtin
をインポートすることで、これらの情報にアクセスできます。
コンパイラビルトインは、マルチプラットフォーム対応、クロスビルド、アトミック操作、リフレクションなどで利用します。これらのトピックに現時点で興味がない場合は、この節はスキップしても問題ありません。
コンパイラが組込みで持っている情報を全てを見たい場合、次のコマンドを実行します。
$ zen build-exe --builtin
ノート:
zen builtin
コマンドは非推奨となりました。
ここでは、その中から特によく利用するものについて解説を行います。
コンパイラビルトインの用途の1つとして、コンパイル時にターゲット環境に合わせて分岐を実行する、というものが挙げられます。ビルドターゲットのOSごとに異なるメッセージを表示する例を示します。
まずbuiltin
をインポートします。ターゲットのOS情報は、builtin.os.tag
に格納されており、その値はstd.Target.Os.Tag
(大文字O
) で定義されている列挙型です。そこで、switch
のパターンは、各列挙型のヴァリアントとします。
examples/ch07-builtins/src/builtin.zen:2:11
const builtin = @import("builtin");
const Target = std.Target;
const message = switch (builtin.os.tag) {
.windows => "hello Windows!",
.macosx => "hello macOS!",
.linux => "hello Linux!",
else => "hello others!",
};
これでmessage
にはターゲット環境に合わせた文字列が格納されます。ためしに表示してみます。
examples/ch07-builtins/src/builtin.zen:13:15
test "simple builtin usage" {
std.debug.warn("{}\n", .{message});
}
このテストを Linux 環境で実行すると、次の結果になります。
hello Linux!
ビルトインは、コンパイル時計算可能です。そのため、実行時には余分なコストがかかりません。
examples/ch07-builtins/src/builtin.zen:17:22
const equal = std.testing.equal;
test "builtin is comptime known" {
comptime {
equal("hello Linux!", message);
}
}
注意: 上記コードの期待値
hello Linux!
は、お使いのOSに合わせて変更して下さい。
Zenコンパイラがサポートしているターゲット環境です。プロセッサ (CPU) アーキテクチャ、OS、ABIの3つを組み合わせます。
例えば、x86_64-linux-gnu
は、プロセッサアーキテクチャがx86_64
(Intel) 、OSがLinux、ABIがGNUであることを意味します。
Zenがサポートするプロセッサアーキテクチャです。タグ付き共用体std.Target.Arch
にまとめられています。
pub const Arch = union(enum) {
arm: Arm32,
armeb: Arm32,
aarch64: Arm64,
aarch64_be: Arm64,
aarch64_32: Arm64,
arc,
avr,
bpfel,
bpfeb,
hexagon,
mips,
mipsel,
mips64,
mips64el,
msp430,
powerpc,
powerpc64,
powerpc64le,
r600,
amdgcn,
riscv32,
riscv64,
sparc,
sparcv9,
sparcel,
s390x,
tce,
tcele,
thumb: Arm32,
thumbeb: Arm32,
i386,
x86_64,
xcore,
nvptx,
nvptx64,
le32,
le64,
amdil,
amdil64,
hsail,
hsail64,
spir,
spir64,
kalimba: Kalimba,
shave,
lanai,
wasm32,
wasm64,
renderscript32,
renderscript64,
...
};
ARMは32ビット / 64ビットのアーキテクチャがさらに細分化されています。これは、Cortex-A / Cortex-R / Cortex-Mの違いや命令セットアーキテクチャバージョンの違いを識別するためのものです。
ビルドターゲットのアーキテクチャは、builtin.arch
に格納されています。
Intel や AMD の 64ビット CPU 上で 64ビット OS をインストールしている場合のネイティブ環境ではx86_64
です。
examples/ch07-builtins/src/builtin.zen:24:26
test "builtin arch" {
comptime ok(builtin.arch == Target.Arch.x86_64);
}
ZenがサポートするOSです。列挙型std.Target.Os.Tag
にまとめられています。
pub const Target = struct {
...
pub const Os = struct {
...
pub const Tag = enum {
freestanding,
ananas,
cloudabi,
dragonfly,
freebsd,
fuchsia,
ios,
kfreebsd,
linux,
lv2,
macosx,
netbsd,
openbsd,
solaris,
windows,
haiku,
minix,
rtems,
nacl,
cnk,
aix,
cuda,
nvcl,
amdhsa,
ps4,
elfiamcu,
tvos,
watchos,
mesa3d,
contiki,
amdpal,
hermit,
hurd,
wasi,
emscripten,
uefi,
other,
...
ビルドターゲットのOSは、builtin.os.tag
に格納されています。Linux ネイティブ環境で実行する場合は次のテストが OK となります。
examples/ch07-builtins/src/builtin.zen:28:30
test "builtin os" {
comptime ok(builtin.os.tag == .linux);
}
ZenがサポートするABIです。列挙型std.Target.Abi
にまとめられています。
pub const Abi = enum {
none,
gnu,
gnuabin32,
gnuabi64,
gnueabi,
gnueabihf,
gnux32,
code16,
eabi,
eabihf,
android,
musl,
musleabi,
musleabihf,
msvc,
itanium,
cygnus,
coreclr,
simulator,
};
ビルドターゲットのABIは、builtin.abi
に格納されています。デスクトップ Linux 環境では通常 gnu
になります。
examples/ch07-builtins/src/builtin.zen:32:34
test "builtin abi" {
comptime ok(builtin.abi == Target.Abi.gnu);
}
命令セットアーキテクチャの浮動小数点ABI、浮動小数点モード、バイトエンディアンに関連する列挙型です。
pub const FloatABI = enum {
Soft,
SoftFp,
Hard,
};
pub const FloatMode = enum {
Strict,
Optimized,
};
pub const Endian = enum {
Big,
Little,
};
リンク時のグローバルリンケージに関する列挙型です。組込み関数@export
でシンボルをエスクポートするときに、グローバルリンケージを指定するために利用します。
pub const GlobalLinkage = enum {
Internal,
Strong,
Weak,
LinkOnce,
};
アトミックな操作とオーダーに関連する列挙型です。
pub const AtomicRmwOp = enum {
Xchg,
Add,
Sub,
And,
Nand,
Or,
Xor,
Max,
Min,
};
pub const AtomicOrder = enum {
Unordered,
Monotonic,
Acquire,
Release,
AcqRel,
SeqCst,
};
アトミックな (不可分な) データアクセスをする場合は一般に、 不可分性の保証が強いほどアクセス性能が低下します。 そこで Zen では、不可分性とアクセス性能とのバランスを AtomicOrder で指定するようになっています。 この指定内容は LLVM の Atomic Orderings を継承しています。
Unordered
最も不可分性の保証が弱い指定で、未定義動作が起きないこと、およびロック獲得が起きないことが保証されます。
Monotonic
Unordered の保証に加え、このデータアクセスの不可分性が保証されます。
他のデータアクセスとの順番関係は保証されません。
Acquire
Monotonic の保証に加え、データアクセスのためのロック獲得に必要なバリアを提供します。
この指定は C++11 や C でいう memory_order_acquire
に相当します。
Release
Acquire と同様ですが、ロック解放に必要なバリアを提供します。
C++11 や C でいう memory_order_release
に相当します。
AcqRel
Monotonic の保証に加え、データアクセスのためのロックの獲得および解放に必要なバリアを提供します。
C++11 や C でいう memory_order_acq_rel
に相当します。
SeqCst
Monotonic の保証に加え、データ読み出しのための Acquire 動作、およびデータ書き込みのための Release 動作を行います。
更に、SeqCst
が指定された他のデータアクセスとの順番関係が保証されます。
この指定は、C++11 や C でいう memory_order_seq_cst
や、Java の volatile
指定や、gcc 互換な __sync_*
ビルトイン (他に相反する指定がない場合) に相当します。
ビルドモードに関連する列挙型です。
pub const Mode = enum {
Debug,
ReleaseSafe,
ReleaseFast,
ReleaseSmall,
};
TypeInfo
は、Zenの型に関するメタ情報が定義されています。
pub const TypeInfo = union(enum) {
Type: void,
Void: void,
Bool: void,
NoReturn: void,
Int: Int,
Float: Float,
Pointer: Pointer,
Array: Array,
Struct: Struct,
ComptimeFloat: void,
ComptimeInt: void,
Undefined: void,
Null: void,
Optional: Optional,
ErrorUnion: ErrorUnion,
ErrorSet: ErrorSet,
Enum: Enum,
Union: Union,
Fn: Fn,
BoundFn: Fn,
Opaque: void,
Frame: void,
AnyFrame: AnyFrame,
Vector: Vector,
EnumLiteral: void,
Interface: void,
...
};
例えば、配列型を示すタグ Array
のヴァリアント Array
構造体は次のように定義されています。
pub const Array = struct {
len: comptime_int,
child: type,
...
};
型情報は次のようにして組み込み関数 @typeInfo
を使用することで取得することができます。ここで定数 a の型を取得するために @TypeOf
を使用しています。
examples/ch07-builtins/src/builtin.zen:42:49
test "TypeInfo" {
const a = [_]u32{0} ** 10;
const a_type = @typeInfo(@TypeOf(a));
ok(a_type == .Array);
ok(a_type.Array.len == 10);
ok(a_type.Array.child == u32);
}
ビルドターゲットの環境を知るためにはどうすれば良いのでしょうか?zen build-exe --builtin
コマンドを実行すると、ネイティブ環境のデフォルト設定が取得できます。
Linux 環境で実行した場合デフォルト設定は次のようになります。
usingnamespace @import("std").builtin;
const Target = @import("std").Target;
pub const version_major = 0;
pub const version_minor = 8;
pub const version_patch = 20200610;
pub const version_string = "0.8.20200609LTS";
pub const endian = Endian.Little;
pub const output_mode = OutputMode.Exe;
pub const link_mode = LinkMode.Dynamic;
pub const is_test = false;
pub const single_threaded = false;
pub const arch = Target.Arch.x86_64;
pub const abi = Target.Abi.gnu;
pub const compile_output = CompileOutput.Exe;
pub const mcmodel = MCModel.Default;
pub const os = Target.Os{
.tag = .macosx,
.version_range = .{ .semver = .{
.min = .{
.major = 10,
.minor = 14,
.patch = 6,
},
.max = .{
.major = 10,
.minor = 14,
.patch = 6,
},
}},
};
pub const object_format = Target.ObjectFormat.elf;
pub const mode = Mode.Debug;
pub const link_libc = false;
pub const have_error_return_tracing = true;
pub const valgrind_support = true;
pub const position_independent_code = false;
pub const strip_debug_info = false;
pub const lib_dir = "<path to zen>/lib/zen";
pub const std_dir = "<path to zen>/lib/zen/std";
pub const special_dir = "<path to zen>/lib/zen/std/special";
pub const cpu_attrs = packed struct {
const @"16bit-mode" = false;
const @"32bit-mode" = false;
const @"3dnow" = false;
const @"3dnowa" = false;
const @"64bit" = true;
const @"64bit-mode" = true;
const @"adx" = true;
const @"aes" = true;
const @"avx" = true;
const @"avx2" = true;
const @"avx512bf16" = false;
const @"avx512bitalg" = false;
const @"avx512bw" = false;
const @"avx512cd" = false;
const @"avx512dq" = false;
const @"avx512er" = false;
const @"avx512f" = false;
const @"avx512ifma" = false;
const @"avx512pf" = false;
const @"avx512vbmi" = false;
const @"avx512vbmi2" = false;
const @"avx512vl" = false;
const @"avx512vnni" = false;
const @"avx512vp2intersect" = false;
const @"avx512vpopcntdq" = false;
const @"bmi" = true;
const @"bmi2" = true;
const @"branchfusion" = false;
const @"cldemote" = false;
const @"clflushopt" = true;
const @"clwb" = false;
const @"clzero" = false;
const @"cmov" = true;
const @"cx16" = true;
const @"cx8" = true;
const @"enqcmd" = false;
const @"ermsb" = true;
const @"f16c" = true;
const @"false-deps-lzcnt-tzcnt" = false;
const @"false-deps-popcnt" = true;
const @"fast-11bytenop" = false;
const @"fast-15bytenop" = false;
const @"fast-bextr" = false;
const @"fast-gather" = true;
const @"fast-hops" = false;
const @"fast-lzcnt" = false;
const @"fast-partial-ymm-or-zmm-write" = false;
const @"fast-scalar-fsqrt" = true;
const @"fast-scalar-shift-masks" = false;
const @"fast-shld-rotate" = true;
const @"fast-variable-shuffle" = true;
const @"fast-vector-fsqrt" = true;
const @"fast-vector-shift-masks" = false;
const @"fma" = true;
const @"fma4" = false;
const @"fsgsbase" = true;
const @"fxsr" = true;
const @"gfni" = false;
const @"idivl-to-divb" = false;
const @"idivq-to-divl" = true;
const @"invpcid" = true;
const @"lea-sp" = false;
const @"lea-uses-ag" = false;
const @"lwp" = false;
const @"lzcnt" = true;
const @"macrofusion" = true;
const @"merge-to-threeway-branch" = true;
const @"mmx" = true;
const @"movbe" = true;
const @"movdir64b" = false;
const @"movdiri" = false;
const @"mpx" = true;
const @"mwaitx" = false;
const @"nopl" = true;
const @"pad-short-functions" = false;
const @"pclmul" = true;
const @"pconfig" = false;
const @"pku" = false;
const @"popcnt" = true;
const @"prefer-256-bit" = false;
const @"prefetchwt1" = false;
const @"prfchw" = true;
const @"ptwrite" = false;
const @"rdpid" = false;
const @"rdrnd" = true;
const @"rdseed" = true;
const @"retpoline" = false;
const @"retpoline-external-thunk" = false;
const @"retpoline-indirect-branches" = false;
const @"retpoline-indirect-calls" = false;
const @"rtm" = false;
const @"sahf" = true;
const @"sgx" = false;
const @"sha" = false;
const @"shstk" = false;
const @"slow-3ops-lea" = true;
const @"slow-incdec" = false;
const @"slow-lea" = false;
const @"slow-pmaddwd" = false;
const @"slow-pmulld" = false;
const @"slow-shld" = false;
const @"slow-two-mem-ops" = false;
const @"slow-unaligned-mem-16" = false;
const @"slow-unaligned-mem-32" = false;
const @"soft-float" = false;
const @"sse" = true;
const @"sse-unaligned-mem" = false;
const @"sse2" = true;
const @"sse3" = true;
const @"sse4.1" = true;
const @"sse4.2" = true;
const @"sse4a" = false;
const @"ssse3" = true;
const @"tbm" = false;
const @"vaes" = false;
const @"vpclmulqdq" = false;
const @"waitpkg" = false;
const @"wbnoinvd" = false;
const @"x87" = true;
const @"xop" = false;
const @"xsave" = true;
const @"xsavec" = true;
const @"xsaveopt" = true;
const @"xsaves" = true;
};
これらの設定は、コマンドラインオプションや、ビルドスクリプトの設定によって変更することが可能です。例えば、クロスビルドのターゲットとして、ARM Cortex-M3 (-target thumb-freestanding-eabi
) を指定して、ビルドモードをリリースセーフモード (--release-safe
) にすると、次のようになります。
ターゲットアーキテクチャや浮動小数点ABI、リリースモードなどがネイティブ環境とは異なってきます。上のネイティブ環境をターゲットとした出力と見比べて見て下さい。
$ zen build-exe --builtin -target thumb-freestanding-eabi --release-safe
usingnamespace @import("std").builtin;
const Target = @import("std").Target;
pub const version_major = 0;
pub const version_minor = 8;
pub const version_patch = 20200610;
pub const version_string = "0.8.20200609LTS";
pub const endian = Endian.Little;
pub const output_mode = OutputMode.Exe;
pub const link_mode = LinkMode.Static;
pub const is_test = false;
pub const single_threaded = false;
pub const arch = Target.Arch.thumb;
pub const abi = Target.Abi.eabi;
pub const compile_output = CompileOutput.Exe;
pub const mcmodel = MCModel.Default;
pub const os = Target.Os{
.tag = .freestanding,
.version_range = .{ .none = {} }
};
pub const object_format = Target.ObjectFormat.elf;
pub const mode = Mode.ReleaseSafe;
pub const link_libc = false;
pub const have_error_return_tracing = true;
pub const valgrind_support = false;
pub const position_independent_code = false;
pub const strip_debug_info = false;
pub const lib_dir = "<path to zen>/lib/zen";
pub const std_dir = "<path to zen>/lib/zen/std";
pub const special_dir = "<path to zen>/lib/zen/std/special";
pub const cpu_attrs = packed struct {
const @"32bit" = false;
const @"8msecext" = false;
const @"a12" = false;
const @"a15" = false;
const @"a17" = false;
const @"a32" = false;
const @"a35" = false;
const @"a5" = false;
const @"a53" = false;
const @"a55" = false;
const @"a57" = false;
const @"a7" = false;
const @"a72" = false;
const @"a73" = false;
const @"a75" = false;
const @"a76" = false;
const @"a8" = false;
const @"a9" = false;
const @"aclass" = false;
const @"acquire-release" = false;
const @"aes" = false;
const @"armv2" = false;
const @"armv2a" = false;
const @"armv3" = false;
const @"armv3m" = false;
const @"armv4" = false;
const @"armv4t" = false;
const @"armv5t" = false;
const @"armv5te" = false;
const @"armv5tej" = false;
const @"armv6" = false;
const @"armv6-m" = false;
const @"armv6j" = false;
const @"armv6k" = false;
const @"armv6kz" = false;
const @"armv6s-m" = false;
const @"armv6t2" = false;
const @"armv7-a" = false;
const @"armv7-m" = false;
const @"armv7-r" = false;
const @"armv7e-m" = false;
const @"armv7k" = false;
const @"armv7s" = false;
const @"armv7ve" = false;
const @"armv8-a" = false;
const @"armv8-m.base" = false;
const @"armv8-m.main" = false;
const @"armv8-r" = false;
const @"armv8.1-a" = false;
const @"armv8.1-m.main" = false;
const @"armv8.2-a" = false;
const @"armv8.3-a" = false;
const @"armv8.4-a" = false;
const @"armv8.5-a" = false;
const @"avoid-movs-shop" = false;
const @"avoid-partial-cpsr" = false;
const @"cheap-predicable-cpsr" = false;
const @"crc" = false;
const @"crypto" = false;
const @"d32" = false;
const @"db" = false;
const @"dfb" = false;
const @"disable-postra-scheduler" = false;
const @"dont-widen-vmovs" = false;
const @"dotprod" = false;
const @"dsp" = false;
const @"execute-only" = false;
const @"expand-fp-mlx" = false;
const @"exynos" = false;
const @"fp-armv8" = false;
const @"fp-armv8d16" = false;
const @"fp-armv8d16sp" = false;
const @"fp-armv8sp" = false;
const @"fp16" = false;
const @"fp16fml" = false;
const @"fp64" = false;
const @"fpao" = false;
const @"fpregs" = false;
const @"fpregs16" = false;
const @"fpregs64" = false;
const @"fullfp16" = false;
const @"fuse-aes" = false;
const @"fuse-literals" = false;
const @"hwdiv" = false;
const @"hwdiv-arm" = false;
const @"iwmmxt" = false;
const @"iwmmxt2" = false;
const @"krait" = false;
const @"kryo" = false;
const @"lob" = false;
const @"long-calls" = false;
const @"loop-align" = false;
const @"m3" = false;
const @"mclass" = false;
const @"mp" = false;
const @"muxed-units" = false;
const @"mve" = false;
const @"mve.fp" = false;
const @"nacl-trap" = false;
const @"neon" = false;
const @"neon-fpmovs" = false;
const @"neonfp" = false;
const @"no-branch-predictor" = false;
const @"no-movt" = false;
const @"no-neg-immediates" = false;
const @"noarm" = false;
const @"nonpipelined-vfp" = false;
const @"perfmon" = false;
const @"prefer-ishst" = false;
const @"prefer-vmovsr" = false;
const @"prof-unpr" = false;
const @"r4" = false;
const @"r5" = false;
const @"r52" = false;
const @"r7" = false;
const @"ras" = false;
const @"rclass" = false;
const @"read-tp-hard" = false;
const @"reserve-r9" = false;
const @"ret-addr-stack" = false;
const @"sb" = false;
const @"sha2" = false;
const @"slow-fp-brcc" = false;
const @"slow-load-D-subreg" = false;
const @"slow-odd-reg" = false;
const @"slow-vdup32" = false;
const @"slow-vgetlni32" = false;
const @"slowfpvmlx" = false;
const @"soft-float" = false;
const @"splat-vfp-neon" = false;
const @"strict-align" = false;
const @"swift" = false;
const @"thumb-mode" = true;
const @"thumb2" = false;
const @"trustzone" = false;
const @"use-aa" = false;
const @"use-misched" = false;
const @"v4t" = true;
const @"v5t" = false;
const @"v5te" = false;
const @"v6" = false;
const @"v6k" = false;
const @"v6m" = false;
const @"v6t2" = false;
const @"v7" = false;
const @"v7clrex" = false;
const @"v8" = false;
const @"v8.1a" = false;
const @"v8.1m.main" = false;
const @"v8.2a" = false;
const @"v8.3a" = false;
const @"v8.4a" = false;
const @"v8.5a" = false;
const @"v8m" = false;
const @"v8m.main" = false;
const @"vfp2" = false;
const @"vfp2d16" = false;
const @"vfp2d16sp" = false;
const @"vfp2sp" = false;
const @"vfp3" = false;
const @"vfp3d16" = false;
const @"vfp3d16sp" = false;
const @"vfp3sp" = false;
const @"vfp4" = false;
const @"vfp4d16" = false;
const @"vfp4d16sp" = false;
const @"vfp4sp" = false;
const @"virtualization" = false;
const @"vldn-align" = false;
const @"vmlx-forwarding" = false;
const @"vmlx-hazards" = false;
const @"wide-stride-vfp" = false;
const @"xscale" = false;
const @"zcz" = false;
};
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.