第7章 コンパイル結果のアセンブリを読む
7.1 この章で学ぶこと
この章で学ぶ内容は以下のとおりです。
学ぶこと |
ポイント |
|---|---|
定数畳み込み最適化 |
|
|
|
文字列オブジェクトのレイアウト |
データポインタ・長さ・タグ・関数ポインタ 2 本がスタック上に並ぶ様子 |
引数テーブルとスコープ最適化 |
多引数 |
後片付けパターンの繰り返し |
各 |
7.2 対象コードとアセンブリ出力
前章では、言語基礎の最小サンプル(リスト6-1)を示しました。
この章では、そのコンパイル結果(リスト7-2)を手がかりに、main() の機械語を段階的に追います。
対象のソースコードは以下のとおりです(前章リスト6-1 の再掲)。
def main():
var n: Int = 42
var doubled = n * 2
var xs: List[Int] = [1, 2, 3]
var label = String("count")
print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
リスト7-1(再掲): language_basics_minimal.mojo
このコードをコンパイルすると、実際には機械語へ変換されます。
language_basics_minimal.o:
(__TEXT,__text) section
_language_basics_minimal::main():
; def main():
0: 48 81 ec b8 04 00 00 subq $0x4b8, %rsp
; var n: Int = 42
7: 48 c7 84 24 e8 01 00 00 2a 00 00 00 movq $0x2a, 0x1e8(%rsp)
; var doubled = n * 2
13: 48 c7 84 24 f0 01 00 00 54 00 00 00 movq $0x54, 0x1f0(%rsp)
; var xs: List[Int] = [1, 2, 3]
1f: 48 c7 84 24 f8 01 00 00 01 00 00 00 movq $0x1, 0x1f8(%rsp)
2b: 48 c7 84 24 00 02 00 00 02 00 00 00 movq $0x2, 0x200(%rsp)
37: 48 c7 84 24 08 02 00 00 03 00 00 00 movq $0x3, 0x208(%rsp)
43: 48 8d 84 24 08 02 00 00 leaq 0x208(%rsp), %rax
4b: 48 89 84 24 20 02 00 00 movq %rax, 0x220(%rsp)
53: 48 8d 84 24 00 02 00 00 leaq 0x200(%rsp), %rax
5b: 48 89 84 24 18 02 00 00 movq %rax, 0x218(%rsp)
63: 48 8d 84 24 f8 01 00 00 leaq 0x1f8(%rsp), %rax
6b: 48 89 84 24 10 02 00 00 movq %rax, 0x210(%rsp)
73: 90 nop
74: 48 8d 84 24 10 02 00 00 leaq 0x210(%rsp), %rax
7c: 48 89 84 24 38 01 00 00 movq %rax, 0x138(%rsp)
84: 48 89 84 24 e0 03 00 00 movq %rax, 0x3e0(%rsp)
8c: 48 89 84 24 28 02 00 00 movq %rax, 0x228(%rsp)
94: 48 89 84 24 30 02 00 00 movq %rax, 0x230(%rsp)
9c: 48 89 84 24 38 02 00 00 movq %rax, 0x238(%rsp)
a4: 48 89 84 24 e8 03 00 00 movq %rax, 0x3e8(%rsp)
ac: 48 89 84 24 40 02 00 00 movq %rax, 0x240(%rsp)
b4: 48 89 84 24 48 02 00 00 movq %rax, 0x248(%rsp)
bc: 48 89 84 24 f0 03 00 00 movq %rax, 0x3f0(%rsp)
; var xs: List[Int] = [1, 2, 3]
c4: 90 nop
c5: 48 89 84 24 f8 03 00 00 movq %rax, 0x3f8(%rsp)
cd: 48 c7 84 24 00 04 00 00 03 00 00 00 movq $0x3, 0x400(%rsp)
d9: 90 nop
da: 48 89 84 24 08 04 00 00 movq %rax, 0x408(%rsp)
e2: 48 c7 84 24 10 04 00 00 03 00 00 00 movq $0x3, 0x410(%rsp)
ee: 90 nop
ef: 48 89 84 24 18 04 00 00 movq %rax, 0x418(%rsp)
f7: 48 c7 84 24 20 04 00 00 03 00 00 00 movq $0x3, 0x420(%rsp)
103: 90 nop
104: 48 89 84 24 28 04 00 00 movq %rax, 0x428(%rsp)
10c: 48 c7 84 24 30 04 00 00 03 00 00 00 movq $0x3, 0x430(%rsp)
; var xs: List[Int] = [1, 2, 3]
118: bf 03 00 00 00 movl $0x3, %edi
11d: 48 89 bc 24 40 01 00 00 movq %rdi, 0x140(%rsp)
125: 48 8d b4 24 50 02 00 00 leaq 0x250(%rsp), %rsi
12d: 48 89 b4 24 50 01 00 00 movq %rsi, 0x150(%rsp)
135: e8 00 00 00 00 callq "_std::collections::list::List::__init__(capacity:::SIMD[::DType(int), ::SIMDLength(1)]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>]"
13a: 48 8b b4 24 40 01 00 00 movq 0x140(%rsp), %rsi
142: 48 8b bc 24 50 01 00 00 movq 0x150(%rsp), %rdi
14a: e8 00 00 00 00 callq "_std::collections::list::List::_annotate_increase(::List[$0],::SIMD[::DType(int), ::SIMDLength(1)]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>]"
14f: 48 8b bc 24 50 01 00 00 movq 0x150(%rsp), %rdi
157: 48 8d b4 24 68 02 00 00 leaq 0x268(%rsp), %rsi
15f: 48 89 b4 24 30 01 00 00 movq %rsi, 0x130(%rsp)
167: e8 00 00 00 00 callq "_std::collections::list::List::__init__[LITMutOrigin,::Origin[::Bool(True), $1]]($0$*,__list_literal__:::NoneType)::init_elt::__storage::__init__(::List[$0]%),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>]"
16c: 48 8b bc 24 30 01 00 00 movq 0x130(%rsp), %rdi
174: 48 8d b4 24 70 02 00 00 leaq 0x270(%rsp), %rsi
17c: 48 89 b4 24 48 01 00 00 movq %rsi, 0x148(%rsp)
184: e8 00 00 00 00 callq "_std::collections::list::def[T: Movable, //](idx: Int, var elt: T) -> None{1}_3::__init__($0$),impl=[typevalue<#kgen.instref<\"std::collections::list::List::__init__[LITMutOrigin,::Origin[::Bool(True), $1]]($0$*,__list_literal__:::NoneType)::init_elt::__storage,T=[typevalue<#kgen.instref<\\1B\\22std::builtin::simd::SIMD,dtype=index,length=1\\22>>, scalar<index>],self`2x3={ }\">>, struct<(pointer<struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>>) memoryOnly>]"
189: 48 8b bc 24 38 01 00 00 movq 0x138(%rsp), %rdi
191: 48 8b b4 24 40 01 00 00 movq 0x140(%rsp), %rsi
199: 48 8b 94 24 48 01 00 00 movq 0x148(%rsp), %rdx
1a1: e8 00 00 00 00 callq "_std::builtin::variadics::VariadicList::consume_elements[def[element_type: AnyType, //](idx: Int, var elt: element_type) -> None{1} & ::AnyType & ::Deinitable & ::Movable](::VariadicList[$0, $1, $2, $3, $4]$,$5){$4._mlir_value,(eq $5.element_type, $3)},elt_is_mutable=true,element_type=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>],is_owned=true,elt_handler.T`2x1=[typevalue<#kgen.instref<\"std::collections::list::def[T: Movable, //](idx: Int, var elt: T) -> None{1}_3,impl=[typevalue<#kgen.instref<\\1B\\22std::collections::list::List::__init__[LITMutOrigin,::Origin[::Bool(True), $1]]($0$*,__list_literal__:::NoneType)::init_elt::__storage,T=[typevalue<#kgen.instref<\\\\1B\\\\22std::builtin::simd::SIMD,dtype=index,length=1\\\\22>>, scalar<index>],self`2x3={ }\\22>>, struct<(pointer<struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>>) memoryOnly>],origin_set={ }\">>, struct<(struct<(pointer<struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>>) memoryOnly>) memoryOnly>]"
1a6: 48 8b bc 24 48 01 00 00 movq 0x148(%rsp), %rdi
1ae: e8 00 00 00 00 callq "_std::collections::list::def[T: Movable, //](idx: Int, var elt: T) -> None{1}_3::__deinit__(::def[T: Movable, //](idx: Int, var elt: T) -> None{1}_3[$0, $1]$),impl=[typevalue<#kgen.instref<\"std::collections::list::List::__init__[LITMutOrigin,::Origin[::Bool(True), $1]]($0$*,__list_literal__:::NoneType)::init_elt::__storage,T=[typevalue<#kgen.instref<\\1B\\22std::builtin::simd::SIMD,dtype=index,length=1\\22>>, scalar<index>],self`2x3={ }\">>, struct<(pointer<struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>>) memoryOnly>]"
1b3: 48 8b bc 24 50 01 00 00 movq 0x150(%rsp), %rdi
1bb: 48 c7 84 24 58 02 00 00 03 00 00 00 movq $0x3, 0x258(%rsp)
; var label = String("count")
1c7: 48 8d 84 24 80 02 00 00 leaq 0x280(%rsp), %rax
1cf: 48 89 84 24 58 01 00 00 movq %rax, 0x158(%rsp)
1d7: 48 c7 84 24 80 02 00 00 05 00 00 00 movq $0x5, 0x280(%rsp)
1e3: 48 8d 84 24 78 02 00 00 leaq 0x278(%rsp), %rax
1eb: 48 89 84 24 60 01 00 00 movq %rax, 0x160(%rsp)
1f3: 48 8d 05 00 00 00 00 leaq _static_string_3abc19b547835280(%rip), %rax
1fa: 48 89 84 24 90 02 00 00 movq %rax, 0x290(%rsp)
202: 48 89 84 24 98 02 00 00 movq %rax, 0x298(%rsp)
20a: 48 89 84 24 78 02 00 00 movq %rax, 0x278(%rsp)
212: 48 8d 84 24 88 02 00 00 leaq 0x288(%rsp), %rax
21a: 48 89 84 24 68 01 00 00 movq %rax, 0x168(%rsp)
222: 48 b8 00 00 00 00 00 00 00 20 movabsq $0x2000000000000000, %rax
22c: 48 89 84 24 88 02 00 00 movq %rax, 0x288(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
234: 48 8d 8c 24 a8 02 00 00 leaq 0x2a8(%rsp), %rcx
23c: 48 89 8c 24 70 01 00 00 movq %rcx, 0x170(%rsp)
244: 48 c7 84 24 a8 02 00 00 02 00 00 00 movq $0x2, 0x2a8(%rsp)
250: 48 8d 8c 24 a0 02 00 00 leaq 0x2a0(%rsp), %rcx
258: 48 89 8c 24 78 01 00 00 movq %rcx, 0x178(%rsp)
260: 48 8d 0d 00 00 00 00 leaq _static_string_8cc7ea4ad907a4ea(%rip), %rcx
267: 48 89 8c 24 b8 02 00 00 movq %rcx, 0x2b8(%rsp)
26f: 48 89 8c 24 c0 02 00 00 movq %rcx, 0x2c0(%rsp)
277: 48 89 8c 24 a0 02 00 00 movq %rcx, 0x2a0(%rsp)
27f: 48 8d 8c 24 b0 02 00 00 leaq 0x2b0(%rsp), %rcx
287: 48 89 8c 24 80 01 00 00 movq %rcx, 0x180(%rsp)
28f: 48 89 84 24 b0 02 00 00 movq %rax, 0x2b0(%rsp)
297: 48 8d 8c 24 d0 02 00 00 leaq 0x2d0(%rsp), %rcx
29f: 48 89 8c 24 88 01 00 00 movq %rcx, 0x188(%rsp)
2a7: 48 c7 84 24 d0 02 00 00 05 00 00 00 movq $0x5, 0x2d0(%rsp)
2b3: 48 8d 8c 24 c8 02 00 00 leaq 0x2c8(%rsp), %rcx
2bb: 48 89 8c 24 90 01 00 00 movq %rcx, 0x190(%rsp)
2c3: 48 8d 0d 00 00 00 00 leaq _static_string_d170193af0361179(%rip), %rcx
2ca: 48 89 8c 24 e0 02 00 00 movq %rcx, 0x2e0(%rsp)
2d2: 48 89 8c 24 e8 02 00 00 movq %rcx, 0x2e8(%rsp)
2da: 48 89 8c 24 c8 02 00 00 movq %rcx, 0x2c8(%rsp)
2e2: 48 8d 8c 24 d8 02 00 00 leaq 0x2d8(%rsp), %rcx
2ea: 48 89 8c 24 98 01 00 00 movq %rcx, 0x198(%rsp)
2f2: 48 89 84 24 d8 02 00 00 movq %rax, 0x2d8(%rsp)
2fa: 48 8d 8c 24 f8 02 00 00 leaq 0x2f8(%rsp), %rcx
302: 48 89 8c 24 a0 01 00 00 movq %rcx, 0x1a0(%rsp)
30a: 48 c7 84 24 f8 02 00 00 01 00 00 00 movq $0x1, 0x2f8(%rsp)
316: 48 8d 8c 24 f0 02 00 00 leaq 0x2f0(%rsp), %rcx
31e: 48 89 8c 24 a8 01 00 00 movq %rcx, 0x1a8(%rsp)
326: 48 8d 0d 00 00 00 00 leaq _static_string_a8d4ace0dc8d360e(%rip), %rcx
32d: 48 89 8c 24 d0 01 00 00 movq %rcx, 0x1d0(%rsp)
335: 48 89 8c 24 08 03 00 00 movq %rcx, 0x308(%rsp)
33d: 48 89 8c 24 10 03 00 00 movq %rcx, 0x310(%rsp)
345: 48 89 8c 24 f0 02 00 00 movq %rcx, 0x2f0(%rsp)
34d: 48 8d 8c 24 00 03 00 00 leaq 0x300(%rsp), %rcx
355: 48 89 8c 24 b0 01 00 00 movq %rcx, 0x1b0(%rsp)
35d: 48 89 84 24 00 03 00 00 movq %rax, 0x300(%rsp)
365: 48 8d 8c 24 20 03 00 00 leaq 0x320(%rsp), %rcx
36d: 48 89 8c 24 b8 01 00 00 movq %rcx, 0x1b8(%rsp)
375: 48 c7 84 24 20 03 00 00 01 00 00 00 movq $0x1, 0x320(%rsp)
381: 48 8d 8c 24 18 03 00 00 leaq 0x318(%rsp), %rcx
389: 48 89 8c 24 c0 01 00 00 movq %rcx, 0x1c0(%rsp)
391: 48 8d 0d 00 00 00 00 leaq _static_string_0308bb2145aa4faa(%rip), %rcx
398: 48 89 8c 24 30 03 00 00 movq %rcx, 0x330(%rsp)
3a0: 48 89 8c 24 38 03 00 00 movq %rcx, 0x338(%rsp)
3a8: 48 89 8c 24 18 03 00 00 movq %rcx, 0x318(%rsp)
3b0: 48 8d 8c 24 28 03 00 00 leaq 0x328(%rsp), %rcx
3b8: 48 89 8c 24 c8 01 00 00 movq %rcx, 0x1c8(%rsp)
3c0: 48 89 84 24 28 03 00 00 movq %rax, 0x328(%rsp)
3c8: 90 nop
3c9: 48 8b 84 24 58 02 00 00 movq 0x258(%rsp), %rax
3d1: 48 89 84 24 d8 01 00 00 movq %rax, 0x1d8(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
3d9: e8 00 00 00 00 callq "_std::collections::list::List::__deinit__(::List[$0]$){conforms_to($0, ::AnyType & ::Deinitable)},T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>]"
3de: 48 8b 84 24 d0 01 00 00 movq 0x1d0(%rsp), %rax
3e6: 48 8b 94 24 d8 01 00 00 movq 0x1d8(%rsp), %rdx
3ee: 48 89 94 24 40 03 00 00 movq %rdx, 0x340(%rsp)
3f6: 90 nop
3f7: 90 nop
3f8: 48 89 84 24 38 04 00 00 movq %rax, 0x438(%rsp)
400: 48 c7 84 24 40 04 00 00 01 00 00 00 movq $0x1, 0x440(%rsp)
40c: 48 c7 84 24 48 04 00 00 01 00 00 00 movq $0x1, 0x448(%rsp)
418: 48 89 84 24 48 03 00 00 movq %rax, 0x348(%rsp)
420: 48 89 84 24 50 03 00 00 movq %rax, 0x350(%rsp)
428: 48 89 84 24 50 04 00 00 movq %rax, 0x450(%rsp)
430: 48 89 84 24 58 04 00 00 movq %rax, 0x458(%rsp)
438: 48 c7 84 24 60 04 00 00 01 00 00 00 movq $0x1, 0x460(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
444: 90 nop
445: 90 nop
446: 48 8d 05 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rax
44d: 48 89 84 24 38 04 00 00 movq %rax, 0x438(%rsp)
455: 48 c7 84 24 40 04 00 00 01 00 00 00 movq $0x1, 0x440(%rsp)
461: 48 c7 84 24 48 04 00 00 01 00 00 00 movq $0x1, 0x448(%rsp)
46d: 48 8d 05 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rax
474: 48 89 84 24 58 03 00 00 movq %rax, 0x358(%rsp)
47c: 48 8d 05 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rax
483: 48 89 84 24 60 03 00 00 movq %rax, 0x360(%rsp)
48b: 48 8d 05 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rax
492: 48 89 84 24 50 04 00 00 movq %rax, 0x450(%rsp)
49a: 48 8d 05 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rax
4a1: 48 89 84 24 68 04 00 00 movq %rax, 0x468(%rsp)
4a9: 48 c7 84 24 70 04 00 00 01 00 00 00 movq $0x1, 0x470(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
4b5: 48 8b b4 24 e8 01 00 00 movq 0x1e8(%rsp), %rsi
4bd: 48 8b 8c 24 f0 01 00 00 movq 0x1f0(%rsp), %rcx
4c5: 48 8d 3d 00 00 00 00 leaq _static_string_bbe01a6a523daf15(%rip), %rdi
4cc: 48 89 e0 movq %rsp, %rax
4cf: 48 89 84 24 e0 01 00 00 movq %rax, 0x1e0(%rsp)
4d7: 48 89 78 20 movq %rdi, 0x20(%rax)
4db: 48 8d 3d 00 00 00 00 leaq _static_string_a8d4ace0dc8d360e(%rip), %rdi
4e2: 48 89 78 10 movq %rdi, 0x10(%rax)
4e6: 48 89 50 08 movq %rdx, 0x8(%rax)
4ea: 48 8d 94 24 18 03 00 00 leaq 0x318(%rsp), %rdx
4f2: 48 89 10 movq %rdx, "_language_basics_minimal::main()"(%rax)
4f5: 48 c7 40 38 01 00 00 00 movq $0x1, 0x38(%rax)
4fd: c7 40 30 00 00 00 00 movl $"_language_basics_minimal::main()", 0x30(%rax)
504: 48 c7 40 28 01 00 00 00 movq $0x1, 0x28(%rax)
50c: 48 c7 40 18 01 00 00 00 movq $0x1, 0x18(%rax)
514: 48 8d bc 24 a0 02 00 00 leaq 0x2a0(%rsp), %rdi
51c: 48 8d 94 24 c8 02 00 00 leaq 0x2c8(%rsp), %rdx
524: 4c 8d 84 24 f0 02 00 00 leaq 0x2f0(%rsp), %r8
52c: 4c 8d 8c 24 78 02 00 00 leaq 0x278(%rsp), %r9
534: e8 00 00 00 00 callq "_std::io::io::print[KGENParamList[::Writable & ::AnyType],*::Writable & ::AnyType,LITImmOrigin,::Origin[::Bool(False), $2],::Bool,LITOrigin[$4._mlir_value],::Origin[$4, $5],::Bool,LITOrigin[$7._mlir_value],::Origin[$7, $8]](*$0,sep:::StringSpan[$4, $5, $6],end:::StringSpan[$7, $8, $9],flush:::Bool,file:::FileDescriptor$),Ts.values`=[[typevalue<#kgen.instref<\"std::collections::string::string::String\">>, struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>], [typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>], [typevalue<#kgen.instref<\"std::collections::string::string::String\">>, struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>], [typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>], [typevalue<#kgen.instref<\"std::collections::string::string::String\">>, struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>], [typevalue<#kgen.instref<\"std::collections::string::string::String\">>, struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>], [typevalue<#kgen.instref<\"std::collections::string::string::String\">>, struct<(pointer<none>, scalar<index>, scalar<index>) memoryOnly>], [typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=index,length=1\">>, scalar<index>]],sep.mut`4=false,end.mut`7=false"
539: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
543: 48 23 84 24 28 03 00 00 andq 0x328(%rsp), %rax
54b: 48 83 f8 00 cmpq $0x0, %rax
54f: 0f 84 92 01 00 00 je 0x6e7
555: 48 8b 84 24 c0 01 00 00 movq 0x1c0(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
55d: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
560: 48 83 c0 f8 addq $-0x8, %rax
564: 48 89 84 24 28 01 00 00 movq %rax, 0x128(%rsp)
56c: 48 89 84 24 68 03 00 00 movq %rax, 0x368(%rsp)
574: 48 89 84 24 70 03 00 00 movq %rax, 0x370(%rsp)
57c: 90 nop
57d: 48 8b 8c 24 28 01 00 00 movq 0x128(%rsp), %rcx
585: 48 c7 84 24 78 04 00 00 01 00 00 00 movq $0x1, 0x478(%rsp)
591: 48 89 8c 24 78 03 00 00 movq %rcx, 0x378(%rsp)
599: 48 89 8c 24 80 04 00 00 movq %rcx, 0x480(%rsp)
5a1: 48 c7 c0 ff ff ff ff movq $-0x1, %rax
5a8: f0 lock
5a9: 48 0f c1 01 xaddq %rax, "_language_basics_minimal::main()"(%rcx)
5ad: 48 89 84 24 88 04 00 00 movq %rax, 0x488(%rsp)
5b5: 48 89 84 24 20 01 00 00 movq %rax, 0x120(%rsp)
5bd: 48 8b 84 24 20 01 00 00 movq 0x120(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5c5: 48 83 f8 01 cmpq $0x1, %rax
5c9: 0f 85 14 01 00 00 jne 0x6e3
5cf: eb 00 jmp 0x5d1
5d1: 48 8b bc 24 28 01 00 00 movq 0x128(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5d9: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::__init__(unsafe_owned_ptr:::Pointer[::Bool(True), MutUntrackedOrigin, $0, *?, ::AddressSpace(::SIMDLength(0))]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
5de: 48 89 84 24 18 01 00 00 movq %rax, 0x118(%rsp)
5e6: 48 8b 8c 24 c8 01 00 00 movq 0x1c8(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5ee: 48 b8 00 00 00 00 00 00 00 80 movabsq $-0x8000000000000000, %rax
5f8: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
5fb: 48 83 f8 00 cmpq $0x0, %rax
5ff: 74 0f je 0x610
601: b8 17 00 00 00 movl $0x17, %eax
606: 48 89 84 24 10 01 00 00 movq %rax, 0x110(%rsp)
60e: eb 60 jmp 0x670
610: 48 8b 8c 24 c8 01 00 00 movq 0x1c8(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
618: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
622: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
625: 48 83 f8 00 cmpq $0x0, %rax
629: 0f 95 c0 setne %al
62c: 34 ff xorb $-0x1, %al
62e: a8 01 testb $0x1, %al
630: 75 02 jne 0x634
632: eb 15 jmp 0x649
634: 48 8b 84 24 b8 01 00 00 movq 0x1b8(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
63c: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
63f: 48 89 84 24 08 01 00 00 movq %rax, 0x108(%rsp)
647: eb 17 jmp 0x660
649: 48 8b 84 24 c8 01 00 00 movq 0x1c8(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
651: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
654: 48 c1 e0 03 shlq $0x3, %rax
658: 48 89 84 24 08 01 00 00 movq %rax, 0x108(%rsp)
660: 48 8b 84 24 08 01 00 00 movq 0x108(%rsp), %rax
668: 48 89 84 24 10 01 00 00 movq %rax, 0x110(%rsp)
670: 48 8b 84 24 10 01 00 00 movq 0x110(%rsp), %rax
678: 48 89 84 24 00 01 00 00 movq %rax, 0x100(%rsp)
680: 48 8b bc 24 18 01 00 00 movq 0x118(%rsp), %rdi
688: 48 8b b4 24 00 01 00 00 movq 0x100(%rsp), %rsi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
690: 48 83 c6 08 addq $0x8, %rsi
694: 48 89 f0 movq %rsi, %rax
697: 90 nop
698: 48 89 b4 24 90 04 00 00 movq %rsi, 0x490(%rsp)
6a0: 90 nop
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6a1: 48 89 b4 24 98 04 00 00 movq %rsi, 0x498(%rsp)
6a9: 48 c7 84 24 a0 04 00 00 01 00 00 00 movq $0x1, 0x4a0(%rsp)
6b5: ba 01 00 00 00 movl $0x1, %edx
6ba: 48 89 84 24 a8 04 00 00 movq %rax, 0x4a8(%rsp)
6c2: 48 c7 84 24 b0 04 00 00 01 00 00 00 movq $0x1, 0x4b0(%rsp)
6ce: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::unsafe_with_layout(::ThinAllocation[$0]$,::Layout[$0]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
6d3: 48 89 c7 movq %rax, %rdi
6d6: 48 89 d6 movq %rdx, %rsi
6d9: 48 89 ca movq %rcx, %rdx
6dc: e8 00 00 00 00 callq "_std::memory::alloc::dealloc[::AnyType](::Allocation[$0]$),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
6e1: eb 02 jmp 0x6e5
6e3: eb 00 jmp 0x6e5
6e5: eb 02 jmp 0x6e9
6e7: eb 00 jmp 0x6e9
6e9: 48 8b 8c 24 b0 01 00 00 movq 0x1b0(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6f1: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
6fb: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
6fe: 48 83 f8 00 cmpq $0x0, %rax
702: 0f 84 92 01 00 00 je 0x89a
708: 48 8b 84 24 a8 01 00 00 movq 0x1a8(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
710: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
713: 48 83 c0 f8 addq $-0x8, %rax
717: 48 89 84 24 f8 00 00 00 movq %rax, 0xf8(%rsp)
71f: 48 89 84 24 80 03 00 00 movq %rax, 0x380(%rsp)
727: 48 89 84 24 88 03 00 00 movq %rax, 0x388(%rsp)
72f: 90 nop
730: 48 8b 8c 24 f8 00 00 00 movq 0xf8(%rsp), %rcx
738: 48 c7 84 24 78 04 00 00 01 00 00 00 movq $0x1, 0x478(%rsp)
744: 48 89 8c 24 90 03 00 00 movq %rcx, 0x390(%rsp)
74c: 48 89 8c 24 80 04 00 00 movq %rcx, 0x480(%rsp)
754: 48 c7 c0 ff ff ff ff movq $-0x1, %rax
75b: f0 lock
75c: 48 0f c1 01 xaddq %rax, "_language_basics_minimal::main()"(%rcx)
760: 48 89 84 24 88 04 00 00 movq %rax, 0x488(%rsp)
768: 48 89 84 24 f0 00 00 00 movq %rax, 0xf0(%rsp)
770: 48 8b 84 24 f0 00 00 00 movq 0xf0(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
778: 48 83 f8 01 cmpq $0x1, %rax
77c: 0f 85 14 01 00 00 jne 0x896
782: eb 00 jmp 0x784
784: 48 8b bc 24 f8 00 00 00 movq 0xf8(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
78c: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::__init__(unsafe_owned_ptr:::Pointer[::Bool(True), MutUntrackedOrigin, $0, *?, ::AddressSpace(::SIMDLength(0))]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
791: 48 89 84 24 e8 00 00 00 movq %rax, 0xe8(%rsp)
799: 48 8b 8c 24 b0 01 00 00 movq 0x1b0(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
7a1: 48 b8 00 00 00 00 00 00 00 80 movabsq $-0x8000000000000000, %rax
7ab: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
7ae: 48 83 f8 00 cmpq $0x0, %rax
7b2: 74 0f je 0x7c3
7b4: b8 17 00 00 00 movl $0x17, %eax
7b9: 48 89 84 24 e0 00 00 00 movq %rax, 0xe0(%rsp)
7c1: eb 60 jmp 0x823
7c3: 48 8b 8c 24 b0 01 00 00 movq 0x1b0(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
7cb: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
7d5: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
7d8: 48 83 f8 00 cmpq $0x0, %rax
7dc: 0f 95 c0 setne %al
7df: 34 ff xorb $-0x1, %al
7e1: a8 01 testb $0x1, %al
7e3: 75 02 jne 0x7e7
7e5: eb 15 jmp 0x7fc
7e7: 48 8b 84 24 a0 01 00 00 movq 0x1a0(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
7ef: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
7f2: 48 89 84 24 d8 00 00 00 movq %rax, 0xd8(%rsp)
7fa: eb 17 jmp 0x813
7fc: 48 8b 84 24 b0 01 00 00 movq 0x1b0(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
804: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
807: 48 c1 e0 03 shlq $0x3, %rax
80b: 48 89 84 24 d8 00 00 00 movq %rax, 0xd8(%rsp)
813: 48 8b 84 24 d8 00 00 00 movq 0xd8(%rsp), %rax
81b: 48 89 84 24 e0 00 00 00 movq %rax, 0xe0(%rsp)
823: 48 8b 84 24 e0 00 00 00 movq 0xe0(%rsp), %rax
82b: 48 89 84 24 d0 00 00 00 movq %rax, 0xd0(%rsp)
833: 48 8b bc 24 e8 00 00 00 movq 0xe8(%rsp), %rdi
83b: 48 8b b4 24 d0 00 00 00 movq 0xd0(%rsp), %rsi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
843: 48 83 c6 08 addq $0x8, %rsi
847: 48 89 f0 movq %rsi, %rax
84a: 90 nop
84b: 48 89 b4 24 90 04 00 00 movq %rsi, 0x490(%rsp)
853: 90 nop
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
854: 48 89 b4 24 98 04 00 00 movq %rsi, 0x498(%rsp)
85c: 48 c7 84 24 a0 04 00 00 01 00 00 00 movq $0x1, 0x4a0(%rsp)
868: ba 01 00 00 00 movl $0x1, %edx
86d: 48 89 84 24 a8 04 00 00 movq %rax, 0x4a8(%rsp)
875: 48 c7 84 24 b0 04 00 00 01 00 00 00 movq $0x1, 0x4b0(%rsp)
881: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::unsafe_with_layout(::ThinAllocation[$0]$,::Layout[$0]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
886: 48 89 c7 movq %rax, %rdi
889: 48 89 d6 movq %rdx, %rsi
88c: 48 89 ca movq %rcx, %rdx
88f: e8 00 00 00 00 callq "_std::memory::alloc::dealloc[::AnyType](::Allocation[$0]$),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
894: eb 02 jmp 0x898
896: eb 00 jmp 0x898
898: eb 02 jmp 0x89c
89a: eb 00 jmp 0x89c
89c: 48 8b 8c 24 98 01 00 00 movq 0x198(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
8a4: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
8ae: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
8b1: 48 83 f8 00 cmpq $0x0, %rax
8b5: 0f 84 92 01 00 00 je 0xa4d
8bb: 48 8b 84 24 90 01 00 00 movq 0x190(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
8c3: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
8c6: 48 83 c0 f8 addq $-0x8, %rax
8ca: 48 89 84 24 c8 00 00 00 movq %rax, 0xc8(%rsp)
8d2: 48 89 84 24 98 03 00 00 movq %rax, 0x398(%rsp)
8da: 48 89 84 24 a0 03 00 00 movq %rax, 0x3a0(%rsp)
8e2: 90 nop
8e3: 48 8b 8c 24 c8 00 00 00 movq 0xc8(%rsp), %rcx
8eb: 48 c7 84 24 78 04 00 00 01 00 00 00 movq $0x1, 0x478(%rsp)
8f7: 48 89 8c 24 a8 03 00 00 movq %rcx, 0x3a8(%rsp)
8ff: 48 89 8c 24 80 04 00 00 movq %rcx, 0x480(%rsp)
907: 48 c7 c0 ff ff ff ff movq $-0x1, %rax
90e: f0 lock
90f: 48 0f c1 01 xaddq %rax, "_language_basics_minimal::main()"(%rcx)
913: 48 89 84 24 88 04 00 00 movq %rax, 0x488(%rsp)
91b: 48 89 84 24 c0 00 00 00 movq %rax, 0xc0(%rsp)
923: 48 8b 84 24 c0 00 00 00 movq 0xc0(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
92b: 48 83 f8 01 cmpq $0x1, %rax
92f: 0f 85 14 01 00 00 jne 0xa49
935: eb 00 jmp 0x937
937: 48 8b bc 24 c8 00 00 00 movq 0xc8(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
93f: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::__init__(unsafe_owned_ptr:::Pointer[::Bool(True), MutUntrackedOrigin, $0, *?, ::AddressSpace(::SIMDLength(0))]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
944: 48 89 84 24 b8 00 00 00 movq %rax, 0xb8(%rsp)
94c: 48 8b 8c 24 98 01 00 00 movq 0x198(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
954: 48 b8 00 00 00 00 00 00 00 80 movabsq $-0x8000000000000000, %rax
95e: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
961: 48 83 f8 00 cmpq $0x0, %rax
965: 74 0f je 0x976
967: b8 17 00 00 00 movl $0x17, %eax
96c: 48 89 84 24 b0 00 00 00 movq %rax, 0xb0(%rsp)
974: eb 60 jmp 0x9d6
976: 48 8b 8c 24 98 01 00 00 movq 0x198(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
97e: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
988: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
98b: 48 83 f8 00 cmpq $0x0, %rax
98f: 0f 95 c0 setne %al
992: 34 ff xorb $-0x1, %al
994: a8 01 testb $0x1, %al
996: 75 02 jne 0x99a
998: eb 15 jmp 0x9af
99a: 48 8b 84 24 88 01 00 00 movq 0x188(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
9a2: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
9a5: 48 89 84 24 a8 00 00 00 movq %rax, 0xa8(%rsp)
9ad: eb 17 jmp 0x9c6
9af: 48 8b 84 24 98 01 00 00 movq 0x198(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
9b7: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
9ba: 48 c1 e0 03 shlq $0x3, %rax
9be: 48 89 84 24 a8 00 00 00 movq %rax, 0xa8(%rsp)
9c6: 48 8b 84 24 a8 00 00 00 movq 0xa8(%rsp), %rax
9ce: 48 89 84 24 b0 00 00 00 movq %rax, 0xb0(%rsp)
9d6: 48 8b 84 24 b0 00 00 00 movq 0xb0(%rsp), %rax
9de: 48 89 84 24 a0 00 00 00 movq %rax, 0xa0(%rsp)
9e6: 48 8b bc 24 b8 00 00 00 movq 0xb8(%rsp), %rdi
9ee: 48 8b b4 24 a0 00 00 00 movq 0xa0(%rsp), %rsi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
9f6: 48 83 c6 08 addq $0x8, %rsi
9fa: 48 89 f0 movq %rsi, %rax
9fd: 90 nop
9fe: 48 89 b4 24 90 04 00 00 movq %rsi, 0x490(%rsp)
a06: 90 nop
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
a07: 48 89 b4 24 98 04 00 00 movq %rsi, 0x498(%rsp)
a0f: 48 c7 84 24 a0 04 00 00 01 00 00 00 movq $0x1, 0x4a0(%rsp)
a1b: ba 01 00 00 00 movl $0x1, %edx
a20: 48 89 84 24 a8 04 00 00 movq %rax, 0x4a8(%rsp)
a28: 48 c7 84 24 b0 04 00 00 01 00 00 00 movq $0x1, 0x4b0(%rsp)
a34: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::unsafe_with_layout(::ThinAllocation[$0]$,::Layout[$0]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
a39: 48 89 c7 movq %rax, %rdi
a3c: 48 89 d6 movq %rdx, %rsi
a3f: 48 89 ca movq %rcx, %rdx
a42: e8 00 00 00 00 callq "_std::memory::alloc::dealloc[::AnyType](::Allocation[$0]$),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
a47: eb 02 jmp 0xa4b
a49: eb 00 jmp 0xa4b
a4b: eb 02 jmp 0xa4f
a4d: eb 00 jmp 0xa4f
a4f: 48 8b 8c 24 80 01 00 00 movq 0x180(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
a57: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
a61: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
a64: 48 83 f8 00 cmpq $0x0, %rax
a68: 0f 84 83 01 00 00 je 0xbf1
a6e: 48 8b 84 24 78 01 00 00 movq 0x178(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
a76: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
a79: 48 83 c0 f8 addq $-0x8, %rax
a7d: 48 89 84 24 98 00 00 00 movq %rax, 0x98(%rsp)
a85: 48 89 84 24 b0 03 00 00 movq %rax, 0x3b0(%rsp)
a8d: 48 89 84 24 b8 03 00 00 movq %rax, 0x3b8(%rsp)
a95: 90 nop
a96: 48 8b 8c 24 98 00 00 00 movq 0x98(%rsp), %rcx
a9e: 48 c7 84 24 78 04 00 00 01 00 00 00 movq $0x1, 0x478(%rsp)
aaa: 48 89 8c 24 c0 03 00 00 movq %rcx, 0x3c0(%rsp)
ab2: 48 89 8c 24 80 04 00 00 movq %rcx, 0x480(%rsp)
aba: 48 c7 c0 ff ff ff ff movq $-0x1, %rax
ac1: f0 lock
ac2: 48 0f c1 01 xaddq %rax, "_language_basics_minimal::main()"(%rcx)
ac6: 48 89 84 24 88 04 00 00 movq %rax, 0x488(%rsp)
ace: 48 89 84 24 90 00 00 00 movq %rax, 0x90(%rsp)
ad6: 48 8b 84 24 90 00 00 00 movq 0x90(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
ade: 48 83 f8 01 cmpq $0x1, %rax
ae2: 0f 85 05 01 00 00 jne 0xbed
ae8: eb 00 jmp 0xaea
aea: 48 8b bc 24 98 00 00 00 movq 0x98(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
af2: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::__init__(unsafe_owned_ptr:::Pointer[::Bool(True), MutUntrackedOrigin, $0, *?, ::AddressSpace(::SIMDLength(0))]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
af7: 48 89 84 24 88 00 00 00 movq %rax, 0x88(%rsp)
aff: 48 8b 8c 24 80 01 00 00 movq 0x180(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
b07: 48 b8 00 00 00 00 00 00 00 80 movabsq $-0x8000000000000000, %rax
b11: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
b14: 48 83 f8 00 cmpq $0x0, %rax
b18: 74 0f je 0xb29
b1a: b8 17 00 00 00 movl $0x17, %eax
b1f: 48 89 84 24 80 00 00 00 movq %rax, 0x80(%rsp)
b27: eb 57 jmp 0xb80
b29: 48 8b 8c 24 80 01 00 00 movq 0x180(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
b31: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
b3b: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
b3e: 48 83 f8 00 cmpq $0x0, %rax
b42: 0f 95 c0 setne %al
b45: 34 ff xorb $-0x1, %al
b47: a8 01 testb $0x1, %al
b49: 75 02 jne 0xb4d
b4b: eb 12 jmp 0xb5f
b4d: 48 8b 84 24 70 01 00 00 movq 0x170(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
b55: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
b58: 48 89 44 24 78 movq %rax, 0x78(%rsp)
b5d: eb 14 jmp 0xb73
b5f: 48 8b 84 24 80 01 00 00 movq 0x180(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
b67: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
b6a: 48 c1 e0 03 shlq $0x3, %rax
b6e: 48 89 44 24 78 movq %rax, 0x78(%rsp)
b73: 48 8b 44 24 78 movq 0x78(%rsp), %rax
b78: 48 89 84 24 80 00 00 00 movq %rax, 0x80(%rsp)
b80: 48 8b 84 24 80 00 00 00 movq 0x80(%rsp), %rax
b88: 48 89 44 24 70 movq %rax, 0x70(%rsp)
b8d: 48 8b bc 24 88 00 00 00 movq 0x88(%rsp), %rdi
b95: 48 8b 74 24 70 movq 0x70(%rsp), %rsi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
b9a: 48 83 c6 08 addq $0x8, %rsi
b9e: 48 89 f0 movq %rsi, %rax
ba1: 90 nop
ba2: 48 89 b4 24 90 04 00 00 movq %rsi, 0x490(%rsp)
baa: 90 nop
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
bab: 48 89 b4 24 98 04 00 00 movq %rsi, 0x498(%rsp)
bb3: 48 c7 84 24 a0 04 00 00 01 00 00 00 movq $0x1, 0x4a0(%rsp)
bbf: ba 01 00 00 00 movl $0x1, %edx
bc4: 48 89 84 24 a8 04 00 00 movq %rax, 0x4a8(%rsp)
bcc: 48 c7 84 24 b0 04 00 00 01 00 00 00 movq $0x1, 0x4b0(%rsp)
bd8: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::unsafe_with_layout(::ThinAllocation[$0]$,::Layout[$0]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
bdd: 48 89 c7 movq %rax, %rdi
be0: 48 89 d6 movq %rdx, %rsi
be3: 48 89 ca movq %rcx, %rdx
be6: e8 00 00 00 00 callq "_std::memory::alloc::dealloc[::AnyType](::Allocation[$0]$),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
beb: eb 02 jmp 0xbef
bed: eb 00 jmp 0xbef
bef: eb 02 jmp 0xbf3
bf1: eb 00 jmp 0xbf3
bf3: 48 8b 8c 24 68 01 00 00 movq 0x168(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
bfb: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
c05: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
c08: 48 83 f8 00 cmpq $0x0, %rax
c0c: 0f 84 65 01 00 00 je 0xd77
c12: 48 8b 84 24 60 01 00 00 movq 0x160(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
c1a: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
c1d: 48 83 c0 f8 addq $-0x8, %rax
c21: 48 89 44 24 68 movq %rax, 0x68(%rsp)
c26: 48 89 84 24 c8 03 00 00 movq %rax, 0x3c8(%rsp)
c2e: 48 89 84 24 d0 03 00 00 movq %rax, 0x3d0(%rsp)
c36: 90 nop
c37: 48 8b 4c 24 68 movq 0x68(%rsp), %rcx
c3c: 48 c7 84 24 78 04 00 00 01 00 00 00 movq $0x1, 0x478(%rsp)
c48: 48 89 8c 24 d8 03 00 00 movq %rcx, 0x3d8(%rsp)
c50: 48 89 8c 24 80 04 00 00 movq %rcx, 0x480(%rsp)
c58: 48 c7 c0 ff ff ff ff movq $-0x1, %rax
c5f: f0 lock
c60: 48 0f c1 01 xaddq %rax, "_language_basics_minimal::main()"(%rcx)
c64: 48 89 84 24 88 04 00 00 movq %rax, 0x488(%rsp)
c6c: 48 89 44 24 60 movq %rax, 0x60(%rsp)
c71: 48 8b 44 24 60 movq 0x60(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
c76: 48 83 f8 01 cmpq $0x1, %rax
c7a: 0f 85 f3 00 00 00 jne 0xd73
c80: eb 00 jmp 0xc82
c82: 48 8b 7c 24 68 movq 0x68(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
c87: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::__init__(unsafe_owned_ptr:::Pointer[::Bool(True), MutUntrackedOrigin, $0, *?, ::AddressSpace(::SIMDLength(0))]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
c8c: 48 89 44 24 58 movq %rax, 0x58(%rsp)
c91: 48 8b 8c 24 68 01 00 00 movq 0x168(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
c99: 48 b8 00 00 00 00 00 00 00 80 movabsq $-0x8000000000000000, %rax
ca3: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
ca6: 48 83 f8 00 cmpq $0x0, %rax
caa: 74 0c je 0xcb8
cac: b8 17 00 00 00 movl $0x17, %eax
cb1: 48 89 44 24 50 movq %rax, 0x50(%rsp)
cb6: eb 54 jmp 0xd0c
cb8: 48 8b 8c 24 68 01 00 00 movq 0x168(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
cc0: 48 b8 00 00 00 00 00 00 00 40 movabsq $0x4000000000000000, %rax
cca: 48 23 01 andq "_language_basics_minimal::main()"(%rcx), %rax
ccd: 48 83 f8 00 cmpq $0x0, %rax
cd1: 0f 95 c0 setne %al
cd4: 34 ff xorb $-0x1, %al
cd6: a8 01 testb $0x1, %al
cd8: 75 02 jne 0xcdc
cda: eb 12 jmp 0xcee
cdc: 48 8b 84 24 58 01 00 00 movq 0x158(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
ce4: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
ce7: 48 89 44 24 48 movq %rax, 0x48(%rsp)
cec: eb 14 jmp 0xd02
cee: 48 8b 84 24 68 01 00 00 movq 0x168(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
cf6: 48 8b 00 movq "_language_basics_minimal::main()"(%rax), %rax
cf9: 48 c1 e0 03 shlq $0x3, %rax
cfd: 48 89 44 24 48 movq %rax, 0x48(%rsp)
d02: 48 8b 44 24 48 movq 0x48(%rsp), %rax
d07: 48 89 44 24 50 movq %rax, 0x50(%rsp)
d0c: 48 8b 44 24 50 movq 0x50(%rsp), %rax
d11: 48 89 44 24 40 movq %rax, 0x40(%rsp)
d16: 48 8b 7c 24 58 movq 0x58(%rsp), %rdi
d1b: 48 8b 74 24 40 movq 0x40(%rsp), %rsi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
d20: 48 83 c6 08 addq $0x8, %rsi
d24: 48 89 f0 movq %rsi, %rax
d27: 90 nop
d28: 48 89 b4 24 90 04 00 00 movq %rsi, 0x490(%rsp)
d30: 90 nop
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
d31: 48 89 b4 24 98 04 00 00 movq %rsi, 0x498(%rsp)
d39: 48 c7 84 24 a0 04 00 00 01 00 00 00 movq $0x1, 0x4a0(%rsp)
d45: ba 01 00 00 00 movl $0x1, %edx
d4a: 48 89 84 24 a8 04 00 00 movq %rax, 0x4a8(%rsp)
d52: 48 c7 84 24 b0 04 00 00 01 00 00 00 movq $0x1, 0x4b0(%rsp)
d5e: e8 00 00 00 00 callq "_std::memory::alloc::ThinAllocation::unsafe_with_layout(::ThinAllocation[$0]$,::Layout[$0]),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
d63: 48 89 c7 movq %rax, %rdi
d66: 48 89 d6 movq %rdx, %rsi
d69: 48 89 ca movq %rcx, %rdx
d6c: e8 00 00 00 00 callq "_std::memory::alloc::dealloc[::AnyType](::Allocation[$0]$),T=[typevalue<#kgen.instref<\"std::builtin::simd::SIMD,dtype=ui8,length=1\">>, scalar<ui8>]"
d71: eb 02 jmp 0xd75
d73: eb 00 jmp 0xd75
d75: eb 02 jmp 0xd79
d77: eb 00 jmp 0xd79
; def main():
d79: 48 81 c4 b8 04 00 00 addq $0x4b8, %rsp
d80: c3 retq
d81: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:"_language_basics_minimal::main()"(%rax,%rax)
d8b: 0f 1f 44 00 00 nopl (%rax,%rax)
リスト7-2: language_basics_minimal.asm
7.3 リスト7-2 を段階的に読む
全体を段階的に解説します。
オフセットや命令列は、手元の objdump 結果と Mojo / LLVM の版によってわずかに変わり得ますが、リスト7-2 のダンプを前提に読み進めてください。
ニモニックは第5章 最小サンプル main のアセンブリを読む と同様に AT&T 記法です。
7.3.1 関数プロローグ
0: subq $0x4b8, %rsp
スタックに 1208 バイト(0x4b8)を確保します。
第5章 最小サンプル main のアセンブリを読む の 296 バイトより大きいのは、複数の変数、文字列オブジェクト、引数用テーブルを すべてスタック上に載せるためです。
7.3.2 変数の初期化(コンパイル時定数の最適化)
; var n: Int = 42
7: movq $0x2a, 0x1e8(%rsp)
; var doubled = n * 2
13: movq $0x54, 0x1f0(%rsp)
注目点は、n * 2 の計算が コンパイル時に完了 していることです。
42 * 2 = 84 がそのまま即値として埋め込まれており、実行時に乗算命令は一切発生しません。
Mojo コンパイラ(LLVM)の 定数畳み込み最適化です。
7.3.3 List[Int] = [1, 2, 3] の構築
; 要素をスタックに配置
1f: movq $0x1, 0x1f8(%rsp)
2b: movq $0x2, 0x200(%rsp)
37: movq $0x3, 0x208(%rsp)
まず 3 つの整数をスタック上に並べます。
; 各要素へのポインタのテーブル(末尾から逆順に組み立て)
43: leaq 0x208(%rsp), %rax
4b: movq %rax, 0x220(%rsp) ; &xs[2]
53: leaq 0x200(%rsp), %rax
5b: movq %rax, 0x218(%rsp) ; &xs[1]
63: leaq 0x1f8(%rsp), %rax
6b: movq %rax, 0x210(%rsp) ; &xs[0]
74: leaq 0x210(%rsp), %rax ; ポインタテーブルの先頭(xs[0])
...
118: movl $0x3, %edi ; 要素数 = 3
要素アドレスのテーブルを 末尾(xs[2])から逆順に組み立て、最後にテーブル先頭(xs[0])のアドレスを他のレジスタへ複製します。
Mojo の List は、内部で 要素を指すポインタ列を持つ形としてコードが生成されます。
図7-1: List[Int] = [1, 2, 3] の構築プロセス(要素配置 → ポインタテーブル → 関数呼び出し)
7.3.4 List 構築(内部関数呼び出し)
List[Int] = [1, 2, 3] のリテラル構築は、アセンブリ上で次の関数呼び出し列として現れます。
135: callq "_std::collections::list::List::__init__(capacity:...),T=[...]"
; List のメモリ確保
14a: callq "_std::collections::list::List::_annotate_increase(::List[$0],...),T=[...]"
; 容量アノテーション(3 要素分)
167: callq "_std::collections::list::List::__init__[...]::init_elt::__storage::__init__(...)"
; 要素転送用の一時ハンドル(storage)を初期化
184: callq "_std::collections::list::def[T: Movable, //](idx: Int, var elt: T) -> None{1}_3::__init__(...)"
; 要素を 1 つずつ受け渡すための内部クロージャを初期化
1a1: callq "_std::builtin::variadics::VariadicList::consume_elements[...]"
; 実際の要素の格納
1ae: callq "_std::collections::list::def[...]::__deinit__(...)"
; 転送用クロージャの後始末
各呼び出しが何をするか、順に見ていきます。
① List::__init__(capacity:)
List オブジェクト本体をヒープ上に確保します。
capacity として要素数(ここでは 3)が渡され、その分のメモリ領域を用意します。
この時点ではまだ要素は入っていません。
② List::_annotate_increase(list, n)
確保済みの List に対して「要素が n 個増える」と知らせるアノテーション呼び出しです。
内部の size カウンタを更新し、List が「3 要素を持っている」状態になります。
実際の要素の中身はまだ移動していません。
③〜⑤ 要素転送用クロージャの初期化・実行・後始末
Mojo 1.0.0 では、consume_elements で要素を一括転送する前後に、転送作業を担う一時的な内部クロージャ(init_elt)の初期化(③)と後始末(⑤)が挟まるようになりました。
これは要素の所有権を安全に移動させるための足場で、旧バージョンにはなかった呼び出しです。
⑥ VariadicList::consume_elements(...)
7.3.3 で構築したポインタテーブル(各要素 1, 2, 3 へのアドレス列)を受け取り、実際に List の内部バッファへ要素を転送します。
この呼び出しで初めて [1, 2, 3] という値が List の中に収まります。
Python では [1, 2, 3] と書くだけでリストが作られますが、Mojo ではコンパイラがこれらの段階に展開します。
「どこに置くか(スタック上の要素配置)→ どれだけ入るか(メモリ確保・容量宣言)→ 転送用の足場を用意する → 実際に移す(転送)→ 足場を片付ける」という順序は、安全なメモリ管理のために必要な手順です。
7.3.5 String("count") の構築
第5章 最小サンプル main のアセンブリを読む の Hello, Mojo と同型です。
文字列オブジェクトは データポインタ、長さ、タグビット、関数ポインタ 2 本 というワード列でスタック上に現れます。
"count" 以降の "n=" や " sum=" なども、同じレイアウトで繰り返し構築されます。
図7-2: 文字列オブジェクトの構築(第5章より再掲)
7.3.6 print() の引数構築と呼び出し
print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
x86-64 System V ABI では引数を rdi → rsi → rdx → rcx → r8 → r9 の順に 6 本のレジスタで渡し、7 番目以降はスタックに積みます。
String はオブジェクトのアドレス(leaq)、Int は値そのもの(movq)として渡します。
8 引数の振り分けは次のとおりです。
順序 |
引数 |
型 |
渡し方 |
レジスタ / 場所 |
|---|---|---|---|---|
1 |
|
String |
アドレス( |
|
2 |
|
Int |
値( |
|
3 |
|
String |
アドレス( |
|
4 |
|
Int |
値( |
|
5 |
|
String |
アドレス( |
|
6 |
|
String |
アドレス( |
|
7 |
|
String |
アドレス → スタック |
|
8 |
|
Int |
値 → スタック |
|
新規 String 4 本の構築 は 7.3.5 と同じ手順でスタック上に行われます。
アドレス範囲(目安) |
構築している文字列 |
長さ |
|---|---|---|
|
|
2 |
|
|
5 |
|
|
1 |
|
|
1 |
len(xs) と List の早期解放 がこの節で注目すべき点です。
len(xs) は xs への最後のアクセスです。
Mojo コンパイラはこれを検出し、①値を退避 → ② List::__deinit__ で即解放 → ③退避値を print() に渡す、という手順を取ります。
xs のメモリは print() を待たずに返却されます。
これが Mojo のスコープ最適化で、Python の GC と違い解放タイミングがコンパイル時に確定します。
3c9: movq 0x258(%rsp), %rax ; xs の要素数を取得
3d1: movq %rax, 0x1d8(%rsp) ; 値を退避
3d9: callq "List::__deinit__(...)" ; xs を解放(print より前!)
引数のレジスタ設定とスタック配置 は callq 直前の命令群で行われます。
コンパイラは第1引数から順ではなく最適な順序で命令を並べます。
; Int 値をレジスタへ
4b5: movq 0x1e8(%rsp), %rsi ; n = 42 → rsi(第2引数)
4bd: movq 0x1f0(%rsp), %rcx ; doubled = 84 → rcx(第4引数)
; rax = rsp を基点に 7・8 番目をスタックへ配置
4cc: movq %rsp, %rax
4e6: movq %rdx, 0x8(%rax) ; len(xs)(3e6 で退避した値)→ 0x8(%rax)(第8引数)
4ea: leaq 0x318(%rsp), %rdx
4f2: movq %rdx, (%rax) ; &String("=") → 0x0(%rax)(第7引数)
; String アドレスをレジスタへ
514: leaq 0x2a0(%rsp), %rdi ; String("n=") → rdi(第1引数)
51c: leaq 0x2c8(%rsp), %rdx ; String(" sum=") → rdx(第3引数)
524: leaq 0x2f0(%rsp), %r8 ; String(" ") → r8(第5引数)
52c: leaq 0x278(%rsp), %r9 ; label → r9(第6引数)
534: callq "print(...)"
callq が return address を積むと rsp が 8 下がるため、呼び出し先からは 0x8(%rsp) = 第7引数、0x10(%rsp) = 第8引数として参照されます。
7.3.7 エラーチェックとデストラクタ処理(5 回繰り返し)
print() のあと、スタック上に作った文字列オブジェクトごとに、第1部第5章と同型の 後片付けパターンが繰り返されます(リスト上は次の開始位置から現れます)。
555…String("n=")6e9…String(" sum=")89c…String(" ")a4f…String("count")bf3…String("=")
各ブロックの内部でも、第1部第5章で見た「参照カウントのデクリメント」に続いて、ThinAllocation::__init__ → Layout の算出(アライメント確認と shlq $0x3 による要素サイズ計算) → ThinAllocation::unsafe_with_layout → dealloc という、1.0.0 の Layout ベースの解放経路(第5章 最小サンプル main のアセンブリを読む 5.9 節参照)を通ります。
各ブロックは、おおむね次の骨格です。
図7-3: 文字列オブジェクトの後片付けパターン(①〜⑤、5 回繰り返し)
同じ形が 5 回分 繰り返されるため、コードが非常に長くなります。
7.3.8 関数エピローグ
d79: addq $0x4b8, %rsp ; スタック解放(1208 バイト)
d80: retq ; 呼び出し元へ戻る
d81: 66 2e 0f 1f 84 00 ... ; nopw(マルチバイト NOP、アライメント用パディング)
d8b: 0f 1f 44 00 00 ; nopl(同上)
末尾のマルチバイト NOP は、次の関数の先頭を特定のバイト境界に合わせるためのパディングです。
7.3.9 全体の流れ(まとめ)
7.3.1〜7.3.8 で見てきた各ステップを概観します。 左側の注釈(定数畳み込み、List は複数段階の内部呼び出しで構築、スコープ最適化、後片付けパターン繰り返し)が、この章を通じて押さえてきたポイントです。
図7-4: language_basics_minimal.mojo の実行フロー全体(STEP 1〜9)
第5章 最小サンプル main のアセンブリを読む の Hello, Mojo と比べると、同じ「文字列を組み立てる → 後片付けする」パターンが、引数の数だけ機械的に繰り返される点が大きな違いです。
Mojo が 文字列リテラルを含む引数ごとに独立したオブジェクトとして扱い、それぞれ参照カウントで管理する様子が、ダンプから追いやすくなっています。