rucc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +55 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +46 -0
  7. data/LICENCE +21 -0
  8. data/README.md +82 -0
  9. data/Rakefile +2 -0
  10. data/Vagrantfile +10 -0
  11. data/bin/console +10 -0
  12. data/bin/rspec +2 -0
  13. data/bin/setup +8 -0
  14. data/exe/rucc +7 -0
  15. data/include/8cc.h +48 -0
  16. data/include/float.h +44 -0
  17. data/include/iso646.h +20 -0
  18. data/include/rucc.h +2 -0
  19. data/include/stdalign.h +11 -0
  20. data/include/stdarg.h +52 -0
  21. data/include/stdbool.h +11 -0
  22. data/include/stddef.h +15 -0
  23. data/include/stdnoreturn.h +8 -0
  24. data/lib/rucc.rb +8 -0
  25. data/lib/rucc/case.rb +22 -0
  26. data/lib/rucc/decl.rb +9 -0
  27. data/lib/rucc/enc.rb +9 -0
  28. data/lib/rucc/engine.rb +138 -0
  29. data/lib/rucc/file_io.rb +108 -0
  30. data/lib/rucc/file_io_list.rb +56 -0
  31. data/lib/rucc/gen.rb +1602 -0
  32. data/lib/rucc/int_evaluator.rb +114 -0
  33. data/lib/rucc/k.rb +73 -0
  34. data/lib/rucc/keyword.rb +17 -0
  35. data/lib/rucc/kind.rb +43 -0
  36. data/lib/rucc/label_gen.rb +13 -0
  37. data/lib/rucc/lexer.rb +40 -0
  38. data/lib/rucc/lexer/impl.rb +683 -0
  39. data/lib/rucc/lexer/preprocessor.rb +888 -0
  40. data/lib/rucc/lexer/preprocessor/cond_incl.rb +27 -0
  41. data/lib/rucc/lexer/preprocessor/constructor.rb +54 -0
  42. data/lib/rucc/lexer/preprocessor/pragma.rb +31 -0
  43. data/lib/rucc/lexer/preprocessor/special_macro.rb +110 -0
  44. data/lib/rucc/libc.rb +47 -0
  45. data/lib/rucc/m.rb +7 -0
  46. data/lib/rucc/macro.rb +24 -0
  47. data/lib/rucc/node.rb +530 -0
  48. data/lib/rucc/node/conv.rb +33 -0
  49. data/lib/rucc/op.rb +61 -0
  50. data/lib/rucc/operator.rb +13 -0
  51. data/lib/rucc/option.rb +30 -0
  52. data/lib/rucc/parser.rb +961 -0
  53. data/lib/rucc/parser/break.rb +18 -0
  54. data/lib/rucc/parser/builtin.rb +25 -0
  55. data/lib/rucc/parser/continue.rb +18 -0
  56. data/lib/rucc/parser/do.rb +33 -0
  57. data/lib/rucc/parser/ensure.rb +39 -0
  58. data/lib/rucc/parser/enum.rb +64 -0
  59. data/lib/rucc/parser/expr.rb +493 -0
  60. data/lib/rucc/parser/for.rb +71 -0
  61. data/lib/rucc/parser/func.rb +274 -0
  62. data/lib/rucc/parser/func_call.rb +54 -0
  63. data/lib/rucc/parser/goto.rb +29 -0
  64. data/lib/rucc/parser/if.rb +23 -0
  65. data/lib/rucc/parser/initializer.rb +237 -0
  66. data/lib/rucc/parser/label.rb +31 -0
  67. data/lib/rucc/parser/return.rb +16 -0
  68. data/lib/rucc/parser/struct_and_union.rb +280 -0
  69. data/lib/rucc/parser/switch.rb +117 -0
  70. data/lib/rucc/parser/while.rb +29 -0
  71. data/lib/rucc/pos.rb +11 -0
  72. data/lib/rucc/rmap.rb +22 -0
  73. data/lib/rucc/s.rb +9 -0
  74. data/lib/rucc/static_label_gen.rb +15 -0
  75. data/lib/rucc/t.rb +18 -0
  76. data/lib/rucc/tempname_gen.rb +14 -0
  77. data/lib/rucc/token.rb +114 -0
  78. data/lib/rucc/token_gen.rb +68 -0
  79. data/lib/rucc/type.rb +304 -0
  80. data/lib/rucc/type/check.rb +39 -0
  81. data/lib/rucc/type/conv.rb +29 -0
  82. data/lib/rucc/type_info.rb +21 -0
  83. data/lib/rucc/utf.rb +126 -0
  84. data/lib/rucc/util.rb +111 -0
  85. data/lib/rucc/version.rb +3 -0
  86. data/rucc.gemspec +38 -0
  87. metadata +201 -0
@@ -0,0 +1,11 @@
1
+ // Copyright 2012 Rui Ueyama. Released under the MIT license.
2
+
3
+ #ifndef __STDBOOL_H
4
+ #define __STDBOOL_H
5
+
6
+ #define bool _Bool
7
+ #define true 1
8
+ #define false 0
9
+ #define __bool_true_false_are_defined 1
10
+
11
+ #endif
@@ -0,0 +1,15 @@
1
+ // Copyright 2012 Rui Ueyama. Released under the MIT license.
2
+
3
+ #ifndef __STDDEF_H
4
+ #define __STDDEF_H
5
+
6
+ #define NULL ((void *)0)
7
+
8
+ typedef unsigned long size_t;
9
+ typedef long ptrdiff_t;
10
+ typedef unsigned int wchar_t;
11
+ typedef long double max_align_t;
12
+
13
+ #define offsetof(type, member) ((size_t)&(((type *)0)->member))
14
+
15
+ #endif
@@ -0,0 +1,8 @@
1
+ // Copyright 2012 Rui Ueyama. Released under the MIT license.
2
+
3
+ #ifndef __STDNORETURN_H
4
+ #define __STDNORETURN_H
5
+
6
+ #define noreturn _Noreturn
7
+
8
+ #endif
@@ -0,0 +1,8 @@
1
+ require "rucc/version"
2
+ require "rucc/engine"
3
+
4
+ module Rucc
5
+ def self.root
6
+ File.expand_path '../..', __FILE__
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ module Rucc
2
+ class Case
3
+ # @param [Integer] b
4
+ # @param [Integer] e
5
+ # @param [String] label
6
+ def initialize(b:, e:, label:)
7
+ @b = b
8
+ @e = e
9
+ @label = label
10
+ end
11
+ attr_reader :b, :e, :label
12
+
13
+ class << self
14
+ # @param [Integer] b
15
+ # @param [Integer] e
16
+ # @param [String] label
17
+ def make_case(b, e, label)
18
+ Case.new(b: b, e: e, label: label)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module Rucc
2
+ # Used as parse context
3
+ module DECL
4
+ BODY = "DECL::BODY"
5
+ PARAM = "DECL::PARAM"
6
+ PARAM_TYPEONLY = "DECL::PARAM_TYPEONLY"
7
+ CAST = "DECL::CAST"
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Rucc
2
+ module ENC
3
+ NONE = "ENC::NONE".freeze
4
+ CHAR16 = "ENC::CHAR16".freeze
5
+ CHAR32 = "ENC::CHAR32".freeze
6
+ UTF8 = "ENC::UTF8".freeze
7
+ WCHAR = "ENC::WCHAR".freeze
8
+ end
9
+ end
@@ -0,0 +1,138 @@
1
+ require 'fileutils'
2
+ require "rucc/option"
3
+ require "rucc/parser"
4
+ require "rucc/gen"
5
+
6
+ module Rucc
7
+ class Engine
8
+ # When io is specified, io is used as input source. When io is not specified,
9
+ # ARGV[0] is considered as sourcde file.
10
+ #
11
+ # @param [<String>] argv
12
+ # @param [IO, NilClass] input
13
+ def initialize(argv, input = nil)
14
+ @option = Option.new
15
+ @option.parse!(argv)
16
+
17
+ if input
18
+ @filename = "-"
19
+ else
20
+ @filename = argv.first
21
+ input = File.open(@filename)
22
+ end
23
+
24
+ # Setup lexer
25
+ @lexer = Lexer.new(input, @filename)
26
+
27
+ # Setup parser
28
+ label_gen = LabelGen.new
29
+ @parser = Parser.new(@lexer, label_gen)
30
+ @lexer.expr_reader = -> { @parser.read_expr }
31
+
32
+ # Setup gen
33
+ @out = StringIO.new
34
+ @gen = Gen.new(@out, label_gen)
35
+
36
+ init_environment!
37
+ end
38
+
39
+ # NOTE: Used only for debug
40
+ def lex
41
+ r = []
42
+ while (tok = @lexer.lex).kind != T::EOF
43
+ r.push(tok)
44
+ end
45
+ r
46
+ end
47
+
48
+ def parse
49
+ @parser.read_toplevels
50
+ end
51
+
52
+ def gen
53
+ parse.each do |toplevel_ast|
54
+ @gen.emit_toplevel(toplevel_ast)
55
+ end
56
+ @out.rewind
57
+ @out.read
58
+ end
59
+
60
+ def run!
61
+ asm = gen
62
+
63
+ if @option.dumpasm
64
+ File.write(outfile('s'), asm)
65
+ return
66
+ end
67
+
68
+ File.write(tmpfile('s'), asm)
69
+ assemble!(src: tmpfile('s'), dst: tmpfile('o'))
70
+
71
+ if @option.dontlink
72
+ FileUtils.copy(tmpfile('o'), outfile('o'))
73
+ return
74
+ end
75
+
76
+ link!(src: tmpfile('o'), dst: (@option.outfile || "a.out"))
77
+ end
78
+
79
+ private
80
+
81
+ def tmpfile(ext)
82
+ "/tmp/ruccXXXXXX.#{ext}"
83
+ end
84
+
85
+ def outfile(ext)
86
+ if @option.outfile
87
+ @option.outfile
88
+ else
89
+ @filename.gsub(/\.c$/, ".#{ext}")
90
+ end
91
+ end
92
+
93
+ def assemble!(src:, dst:)
94
+ # TODO(south37) Check status code
95
+ `as -o #{dst} -c #{src}`
96
+ end
97
+
98
+ def link!(src:, dst:)
99
+ # TODO(south37) Check status code
100
+ `/usr/lib/gcc/x86_64-linux-gnu/6/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper -plugin-opt=-fresolution=/tmp/ccGgKweC.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro /usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/6/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/6 -L/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/6/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/6/../../.. #{src} -o #{dst} -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/6/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/crtn.o`
101
+ end
102
+
103
+ def init_environment!
104
+ pre_difined_include_path.each do |path|
105
+ @lexer.append_include_path(path)
106
+ end
107
+
108
+ @option.include_path.each do |path|
109
+ @lexer.append_include_path(path)
110
+ end
111
+
112
+ read_from_string("#include <#{::Rucc.root}/include/rucc.h>")
113
+ end
114
+
115
+ def pre_difined_include_path
116
+ [
117
+ "#{::Rucc.root}/include",
118
+ "/usr/local/lib/rucc/include",
119
+ "/usr/local/include",
120
+ "/usr/include",
121
+ "/usr/include/linux",
122
+ "/usr/include/x86_64-linux-gnu",
123
+ ]
124
+ end
125
+
126
+ # Reads from a string as if the string is a content of input file.
127
+ # Convenient for evaluating small string snippet contaiing preprocessor macros.
128
+ #
129
+ # @param [String] buf
130
+ def read_from_string(buf)
131
+ @lexer.stream_stash([FileIO.new(StringIO.new(buf), "-")])
132
+ parse.each do |toplevel_ast|
133
+ @gen.emit_toplevel(toplevel_ast)
134
+ end
135
+ @lexer.stream_unstash
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,108 @@
1
+ module Rucc
2
+ class FileIO
3
+ EOF = nil
4
+
5
+ # @param [IO] io
6
+ # @param [String] name
7
+ def initialize(io, name)
8
+ @io = io
9
+ @name = name
10
+ @line = 1
11
+ @column = 1
12
+ @ntok = 0 # Token counter
13
+ @buflen = 0
14
+ @buf = Array.new(3)
15
+ @last = Object.new # NOTE: Not use nil because nil means EOF. Set dummy data at first.
16
+
17
+ # TODO(south37) Set @mtime
18
+ # struct stat st;
19
+ # if (fstat(fileno(file), &st) == -1)
20
+ # error("fstat failed: %s", strerror(errno));
21
+ # r->mtime = st.st_mtime;
22
+ end
23
+ attr_reader :name, :line, :column, :ntok
24
+ attr_writer :name, :line
25
+
26
+ # @return [Char, NilClass] nil at EOF
27
+ def readc
28
+ while true do
29
+ c = get
30
+ if c == EOF
31
+ return c
32
+ end
33
+ if (c != "\\")
34
+ return c
35
+ end
36
+ c2 = get
37
+ if c2 == "\n"
38
+ next
39
+ end
40
+ unreadc(c2)
41
+ return c
42
+ end
43
+ end
44
+
45
+ # @param [Char] c
46
+ def unreadc(c)
47
+ return if c == EOF
48
+ Util.assert!{ @buflen < @buf.size }
49
+ @buf[@buflen] = c
50
+ @buflen += 1
51
+ if c == "\n"
52
+ @column = 1
53
+ @line -= 1
54
+ else
55
+ @column -= 1
56
+ end
57
+ end
58
+
59
+ def incr_ntok!
60
+ @ntok += 1
61
+ end
62
+
63
+ def close
64
+ @io.close
65
+ end
66
+
67
+ def mtime
68
+ Util.assert!{ @io.is_a?(File) }
69
+ File.mtime(@io)
70
+ end
71
+
72
+ private
73
+
74
+ # @return [Char, NilClass] nil at EOF
75
+ def get
76
+ if @buflen > 0
77
+ @buflen -= 1
78
+ c = @buf[@buflen]
79
+ else
80
+ c = readc_file
81
+ end
82
+
83
+ if c == "\n"
84
+ @line += 1
85
+ @column = 1
86
+ elsif c != EOF
87
+ @column += 1
88
+ end
89
+ c
90
+ end
91
+
92
+ # @return [Char, NilClass] nil at EOF
93
+ def readc_file
94
+ c = @io.getc
95
+ if c == EOF
96
+ c = (@last == "\n" || @last == EOF) ? nil : "\n"
97
+ elsif c == "\r"
98
+ c2 = @io.getc
99
+ if c2 != "\n"
100
+ @io.ungetc(c2)
101
+ end
102
+ c = "\n"
103
+ end
104
+ @last = c
105
+ c
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,56 @@
1
+ require "forwardable"
2
+
3
+ module Rucc
4
+ class FileIOList
5
+ extend Forwardable
6
+
7
+ # @param [FileIO] file
8
+ def initialize(file)
9
+ @files = [file]
10
+ @stashed = [] # buffer for stashed files
11
+ end
12
+ delegate [:push, :first, :last] => :@files
13
+
14
+ # @return [FileIO]
15
+ def current
16
+ @files.last
17
+ end
18
+
19
+ # @return [Char, NilClass]
20
+ def readc
21
+ while true
22
+ c = current.readc
23
+ if !c.nil? # not EOF
24
+ return c
25
+ end
26
+
27
+ if @files.size == 1
28
+ return c
29
+ end
30
+ f = @files.pop
31
+ f.close
32
+ next
33
+ end
34
+ raise "Must not reach here!"
35
+ end
36
+
37
+ # @param [Char, NilClass]
38
+ def unreadc(c)
39
+ current.unreadc(c)
40
+ end
41
+
42
+ # @param [<FileIO>] files
43
+ def stream_stash(files)
44
+ @stashed.push(@files)
45
+ @files = files
46
+ end
47
+
48
+ def stream_unstash
49
+ @files = @stashed.pop
50
+ end
51
+
52
+ def stream_depth
53
+ @files.size
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,1602 @@
1
+ require "rucc/int_evaluator"
2
+
3
+ module Rucc
4
+ class Gen
5
+ REGS = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"].freeze
6
+ SREGS = ["dil", "sil", "dl", "cl", "r8b", "r9b"].freeze
7
+ MREGS = ["edi", "esi", "edx", "ecx", "r8d", "r9d"].freeze
8
+
9
+ # @param [IO] output
10
+ # @param [LabelGen] label_gen
11
+ def initialize(output, label_gen)
12
+ @output = output
13
+ @label_gen = label_gen
14
+
15
+ @stackpos = nil
16
+
17
+ # number of float and int
18
+ @numgp = nil
19
+ @numfp = nil
20
+ end
21
+
22
+ # @param [Node] v
23
+ def emit_toplevel(v)
24
+ @stackpos = 8
25
+ if v.kind == AST::FUNC
26
+ emit_func_prologue(v)
27
+ emit_expr(v.body)
28
+ emit_ret
29
+ elsif v.kind == AST::DECL
30
+ emit_global_var(v)
31
+ else
32
+ raise "internal error"
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ # @param [String] fmt
39
+ def emit(fmt, *args)
40
+ emit_noindent("\t#{fmt}", *args)
41
+ end
42
+
43
+ # @param [String] fmt
44
+ def emit_noindent(fmt, *args)
45
+ # Replace "#" with "%%" so that vfprintf prints out "#" as "%".
46
+ @output.printf(fmt.gsub('#', '%%'), *args)
47
+ # TODO(south37) Impl dumpstack when necessary
48
+ # if (dumpstack) {
49
+ # for (char *p = fmt; *p; p++)
50
+ # if (*p == '\t')
51
+ # col += TAB - 1;
52
+ # int space = (28 - col) > 0 ? (30 - col) : 2;
53
+ # fprintf(outputfp, "%*c %s:%d", space, '#', get_caller_list(), line);
54
+ # }
55
+ @output.print("\n")
56
+ end
57
+
58
+ # @param [String] label
59
+ def emit_label(label)
60
+ emit("#{label}:")
61
+ end
62
+
63
+ # @param [Integer] n
64
+ # @param [Integer] m
65
+ # @return [Integer]
66
+ def align(n, m)
67
+ rem = n % m
68
+ return (rem == 0) ? n : (n - rem + m)
69
+ end
70
+
71
+ # @param [Integer] reg
72
+ def push_xmm(reg)
73
+ # TODO(south37) Impl SAVE when necessary
74
+ # SAVE
75
+ emit("sub $8, #rsp")
76
+ emit("movsd #xmm#{reg}, (#rsp)")
77
+ @stackpos += 8
78
+ end
79
+
80
+ # @param [Integer] reg
81
+ def pop_xmm(reg)
82
+ # TODO(south37) Impl SAVE when necessary
83
+ # SAVE
84
+ emit("movsd (#rsp), #xmm#{reg}")
85
+ emit("add $8, #rsp");
86
+ @stackpos -= 8;
87
+ Util.assert!{ @stackpos >= 0 }
88
+ end
89
+
90
+ # @param [String] reg
91
+ def push(reg)
92
+ # TODO(south37) Impl SAVE when necessary
93
+ # SAVE
94
+ emit("push ##{reg}")
95
+
96
+ @stackpos += 8
97
+ end
98
+
99
+ # @param [String] reg
100
+ def pop(reg)
101
+ # TODO(south37) Impl SAVE when necessary
102
+ # SAVE
103
+ emit("pop ##{reg}")
104
+ @stackpos -= 8
105
+ Util.assert!{ @stackpos >= 0 }
106
+ end
107
+
108
+ # @param [Node] func
109
+ def emit_func_prologue(func)
110
+ # TODO(south37) Impl SAVE when necessary
111
+ # SAVE
112
+ emit(".text");
113
+ if !func.ty.isstatic
114
+ emit_noindent(".global #{func.fname}")
115
+ end
116
+ emit_noindent("#{func.fname}:")
117
+ emit("nop")
118
+ push("rbp")
119
+ emit("mov #rsp, #rbp")
120
+ off = 0
121
+ if func.ty.hasva
122
+ set_reg_nums(func.params)
123
+ off -= emit_regsave_area
124
+ end
125
+ push_func_params(func.params, off)
126
+ off -= func.params.size * 8
127
+
128
+ localarea = 0
129
+ func.localvars.each do |v|
130
+ size = align(v.ty.size, 8)
131
+ Util.assert!{ size % 8 == 0 }
132
+ off -= size
133
+ v.loff = off
134
+ localarea += size
135
+ end
136
+ if localarea > 0
137
+ emit("sub $#{localarea}, #rsp")
138
+ @stackpos += localarea
139
+ end
140
+ end
141
+
142
+ # @param [<Node>] args
143
+ def set_reg_nums(args)
144
+ @numgp = @numfp = 0
145
+ args.each do |arg|
146
+ if Type.is_flotype(arg.ty)
147
+ @numfp += 1
148
+ else
149
+ @numgp += 1
150
+ end
151
+ end
152
+ end
153
+
154
+ REGAREA_SIZE = 176
155
+
156
+ # @return [Integer]
157
+ def emit_regsave_area
158
+ emit("sub $#{REGAREA_SIZE}, #rsp")
159
+ emit("mov #rdi, (#rsp)")
160
+ emit("mov #rsi, 8(#rsp)")
161
+ emit("mov #rdx, 16(#rsp)")
162
+ emit("mov #rcx, 24(#rsp)")
163
+ emit("mov #r8, 32(#rsp)")
164
+ emit("mov #r9, 40(#rsp)")
165
+ emit("movaps #xmm0, 48(#rsp)")
166
+ emit("movaps #xmm1, 64(#rsp)")
167
+ emit("movaps #xmm2, 80(#rsp)")
168
+ emit("movaps #xmm3, 96(#rsp)")
169
+ emit("movaps #xmm4, 112(#rsp)")
170
+ emit("movaps #xmm5, 128(#rsp)")
171
+ emit("movaps #xmm6, 144(#rsp)")
172
+ emit("movaps #xmm7, 160(#rsp)")
173
+ REGAREA_SIZE
174
+ end
175
+
176
+ # @param [Array] params
177
+ # @param [Integer] off
178
+ def push_func_params(params, off)
179
+ ireg = 0
180
+ xreg = 0
181
+ arg = 2
182
+ params.each do |v|
183
+ if v.ty.kind == Kind::STRUCT
184
+ emit("lea #{arg * 8}(#rbp), #rax")
185
+ size = push_struct(v.ty.size)
186
+ off -= size
187
+ arg += (size / 8)
188
+ elsif Type.is_flotype(v.ty)
189
+ if xreg >= 8
190
+ emit("mov %d(#rbp), #rax", arg * 8)
191
+ arg += 1
192
+ push("rax")
193
+ else
194
+ push_xmm(xreg)
195
+ xreg += 1
196
+ end
197
+ off -= 8
198
+ else
199
+ if ireg >= 6
200
+ if v.ty.kind == Kind::BOOL
201
+ emit("mov #{arg * 8}(#rbp), #al")
202
+ arg += 1
203
+ emit("movzb #al, #eax")
204
+ else
205
+ emit("mov #{arg * 8}(#rbp), #rax")
206
+ arg += 1
207
+ end
208
+ push("rax")
209
+ else
210
+ if v.ty.kind == Kind::BOOL
211
+ emit("movzb ##{SREGS[ireg]}, ##{MREGS[ireg]}")
212
+ end
213
+ push(REGS[ireg])
214
+ ireg += 1
215
+ end
216
+ off -= 8
217
+ end
218
+ v.loff = off
219
+ end
220
+ end
221
+
222
+ # @param [Integer] size
223
+ # @return [Integer]
224
+ def push_struct(size)
225
+ # TODO(south37) Impl SAVE when necessary
226
+ # SAVE;
227
+ aligned = align(size, 8)
228
+ emit("sub $#{aligned}, #rsp")
229
+ emit("mov #rcx, -8(#rsp)")
230
+ emit("mov #r11, -16(#rsp)")
231
+ emit("mov #rax, #rcx")
232
+ i = 0
233
+ while i < size
234
+ emit("movq #{i}(#rcx), #r11")
235
+ emit("mov #r11, #{i}(#rsp)")
236
+ i += 8
237
+ end
238
+ while i < size
239
+ emit("movl #{i}(#rcx), #r11")
240
+ emit("movl #r11d, #{i}(#rsp)")
241
+ i += 4
242
+ end
243
+ while i < size
244
+ emit("movb %d(#rcx), #r11", i)
245
+ emit("movb #r11b, %d(#rsp)", i)
246
+ i += 1
247
+ end
248
+ emit("mov -8(#rsp), #rcx")
249
+ emit("mov -16(#rsp), #r11")
250
+ @stackpos += aligned
251
+ aligned
252
+ end
253
+
254
+ # @param [Node] node
255
+ def emit_expr(node)
256
+ # TODO(south37) Impl SAVE when necessary
257
+ # SAVE
258
+ # maybe_print_source_loc(node)
259
+ case node.kind
260
+ when AST::LITERAL then emit_literal(node)
261
+ when AST::LVAR then emit_lvar(node)
262
+ when AST::GVAR then emit_gvar(node)
263
+ when AST::FUNCDESG then emit_addr(node)
264
+ when AST::FUNCALL
265
+ return if maybe_emit_builtin(node)
266
+ emit_func_call(node)
267
+ when AST::FUNCPTR_CALL then emit_func_call(node)
268
+ when AST::DECL then emit_decl(node)
269
+ when AST::CONV then emit_conv(node)
270
+ when AST::ADDR then emit_addr(node.operand)
271
+ when AST::DEREF then emit_deref(node)
272
+ when AST::IF, AST::TERNARY then emit_ternary(node)
273
+ when AST::GOTO then emit_goto(node)
274
+ when AST::LABEL then (emit_label(node.newlabel) if node.newlabel)
275
+ when AST::RETURN then emit_return(node)
276
+ when AST::COMPOUND_STMT then emit_compound_stmt(node)
277
+ when AST::STRUCT_REF then emit_load_struct_ref(node.struct, node.ty, 0)
278
+ when OP::PRE_INC then emit_pre_inc_dec(node, "add")
279
+ when OP::PRE_DEC then emit_pre_inc_dec(node, "sub")
280
+ when OP::POST_INC then emit_post_inc_dec(node, "add")
281
+ when OP::POST_DEC then emit_post_inc_dec(node, "sub")
282
+ when '!' then emit_lognot(node)
283
+ when '&' then emit_bitand(node)
284
+ when '|' then emit_bitor(node)
285
+ when '~' then emit_bitnot(node)
286
+ when OP::LOGAND then emit_logand(node)
287
+ when OP::LOGOR then emit_logor(node)
288
+ when OP::CAST then emit_cast(node)
289
+ when ',' then emit_comma(node)
290
+ when '=' then emit_assign(node)
291
+ when OP::LABEL_ADDR then emit_label_addr(node)
292
+ when AST::COMPUTED_GOTO then emit_computed_goto(node)
293
+ else emit_binop(node)
294
+ end
295
+ end
296
+
297
+ # @param [Node] node
298
+ def emit_literal(node)
299
+ # TODO(south37) impl SAVE when necessary
300
+ # SAVE
301
+ case node.ty.kind
302
+ when Kind::BOOL, Kind::CHAR, Kind::SHORT
303
+ emit("mov $%u, #rax" % node.ival)
304
+ when Kind::INT
305
+ emit("mov $%u, #rax" % node.ival)
306
+ when Kind::LONG, Kind::LLONG
307
+ emit("mov $%u, #rax" % node.ival)
308
+ when Kind::FLOAT
309
+ if !node.flabel
310
+ node.flabel = @label_gen.next
311
+ emit_noindent(".data")
312
+ emit_label(node.flabel)
313
+ emit(".long #{[node.fval].pack('f').unpack('I')[0]}")
314
+ emit_noindent(".text")
315
+ end
316
+ emit("movss #{node.flabel}(#rip), #xmm0")
317
+ when Kind::DOUBLE, Kind::LDOUBLE
318
+ if !node.flabel
319
+ node.flabel = @label_gen.next
320
+ emit_noindent(".data")
321
+ emit_label(node.flabel)
322
+ emit(".quad #{[node.fval].pack('d').unpack('Q')[0]}")
323
+ emit_noindent(".text")
324
+ end
325
+ emit("movsd #{node.flabel}(#rip), #xmm0")
326
+ when Kind::ARRAY
327
+ if !node.slabel
328
+ node.slabel = @label_gen.next
329
+ emit_noindent(".data")
330
+ emit_label(node.slabel)
331
+ emit(".string \"%s\"", Util.quote_cstring(node.sval))
332
+ emit_noindent(".text")
333
+ end
334
+ emit("lea #{node.slabel}(#rip), #rax")
335
+ else
336
+ raise "internal error"
337
+ end
338
+ end
339
+
340
+ # @param [Node] node
341
+ def emit_lvar(node)
342
+ # TODO(south37) impl SAVE when necessary
343
+ # SAVE;
344
+ ensure_lvar_init(node)
345
+ emit_lload(node.ty, "rbp", node.loff)
346
+ end
347
+
348
+ # @param [Node] node
349
+ def emit_gvar(node)
350
+ # TODO(south37) impl SAVE when necessary
351
+ # SAVE;
352
+ emit_gload(node.ty, node.glabel, 0)
353
+ end
354
+
355
+ # @param [Type] ty
356
+ # @param [String] label
357
+ # @param [Integer] off
358
+ def emit_gload(ty, label, off)
359
+ # TODO(south37) impl SAVE when necessary
360
+ # SAVE;
361
+ if ty.kind == Kind::ARRAY
362
+ if off > 0
363
+ emit("lea %s+#{off}(#rip), #rax", label)
364
+ else
365
+ emit("lea %s(#rip), #rax", label)
366
+ end
367
+ return
368
+ end
369
+ inst = get_load_inst(ty)
370
+ emit("#{inst} %s+#{off}(#rip), #rax", label)
371
+ maybe_emit_bitshift_load(ty)
372
+ end
373
+
374
+ # @param [Node] v
375
+ def emit_global_var(v)
376
+ # TODO(south37) impl SAVE when necessary
377
+ # SAVE;
378
+ if v.declinit
379
+ emit_data(v, 0, 0)
380
+ else
381
+ emit_bss(v)
382
+ end
383
+ end
384
+
385
+ # @param [Node] v
386
+ # @param [Integer] off
387
+ # @param [Integer] depth
388
+ def emit_data(v, off, depth)
389
+ # TODO(south37) impl SAVE when necessary
390
+ # SAVE;
391
+ emit(".data #{depth}")
392
+ if !v.declvar.ty.isstatic
393
+ emit_noindent(".global #{v.declvar.glabel}")
394
+ end
395
+ emit_noindent("#{v.declvar.glabel}:")
396
+ do_emit_data(v.declinit, v.declvar.ty.size, off, depth)
397
+ end
398
+
399
+ # @param [Array] inits
400
+ # @param [Integer] size
401
+ # @param [Integer] off
402
+ # @param [Integer] depth
403
+ def do_emit_data(inits, size, off, depth)
404
+ # TODO(south37) impl SAVE when necessary
405
+ # SAVE;
406
+ i = 0
407
+ while (i < inits.size && 0 < size)
408
+ node = inits[i]
409
+ v = node.initval
410
+ emit_padding(node, off)
411
+ if node.totype.bitsize && (node.totype.bitsize > 0)
412
+ Util.assert!{ node.totype.bitoff == 0 }
413
+ data = IntEvaluator.eval(v).first
414
+ totype = node.totype
415
+ while (i < inits.size)
416
+ node = inits[i]
417
+ if node.totype.bitsize.nil? || (node.totype.bitsize <= 0)
418
+ break
419
+ end
420
+ v = node.initval
421
+ totype = node.totype
422
+ data |= (((1 << totype.bitsize) - 1) & IntEvaluator.eval(v).first) << totype.bitoff
423
+ i += 1
424
+ end
425
+ emit_data_primtype(totype, Node.new(AST::LITERAL, ty: totype, ival: data), depth)
426
+ off += totype.size
427
+ size -= totype.size
428
+ break if i == inits.size
429
+ else
430
+ off += node.totype.size
431
+ size -= node.totype.size
432
+ end
433
+ if v.kind == AST::ADDR
434
+ emit_data_addr(v.operand, depth)
435
+ i += 1
436
+ next
437
+ end
438
+ if (v.kind == AST::LVAR) && v.lvarinit
439
+ do_emit_data(v.lvarinit, v.ty.size, 0, depth)
440
+ i += 1
441
+ next
442
+ end
443
+ emit_data_primtype(node.totype, node.initval, depth)
444
+ i += 1
445
+ end
446
+ emit_zero(size)
447
+ end
448
+
449
+ # @param [Node] node
450
+ # @param [Intyeger] off
451
+ def emit_padding(node, off)
452
+ # TODO(south37) impl SAVE when necessary
453
+ # SAVE;
454
+ diff = node.initoff - off
455
+ Util.assert!{ diff >= 0 }
456
+ emit_zero(diff)
457
+ end
458
+
459
+ # @param [Integer] size
460
+ def emit_zero(size)
461
+ # TODO(south37) impl SAVE when necessary
462
+ # SAVE;
463
+ while (size >= 8) do
464
+ emit(".quad 0")
465
+ size -= 8
466
+ end
467
+ while (size >= 4) do
468
+ emit(".long 0")
469
+ size -= 4
470
+ end
471
+ while (size > 0) do
472
+ emit(".byte 0")
473
+ size -= 1
474
+ end
475
+ end
476
+
477
+ # @param [Type] ty
478
+ # @param [Node] val
479
+ # @param [Integer] depth
480
+ def emit_data_primtype(ty, val, depth)
481
+ # TODO(south37) impl SAVE when necessary
482
+ # SAVE;
483
+ case ty.kind
484
+ when Kind::FLOAT
485
+ emit(".long #{[val.fval].pack('f').unpack('I')[0]}")
486
+ when Kind::DOUBLE
487
+ emit(".quad #{[node.fval].pack('d').unpack('Q')[0]}")
488
+ when Kind::BOOL
489
+ emit(".byte #{IntEvaluator.eval(val).first > 0 ? 1 : 0}")
490
+ when Kind::CHAR
491
+ emit(".byte #{IntEvaluator.eval(val).first}")
492
+ when Kind::SHORT
493
+ emit(".short #{IntEvaluator.eval(val).first}")
494
+ when Kind::INT
495
+ emit(".long #{IntEvaluator.eval(val).first}")
496
+ when Kind::LONG, Kind::LLONG, Kind::PTR
497
+ if val.kind == OP::LABEL_ADDR
498
+ emit(".quad #{val.newlabel}")
499
+ return
500
+ end
501
+
502
+ is_char_ptr = val.operand && (val.operand.ty.kind == Kind::ARRAY && val.operand.ty.ptr.kind == Kind::CHAR)
503
+ if is_char_ptr
504
+ emit_data_charptr(val.operand.sval, depth)
505
+ elsif val.kind == AST::GVAR
506
+ emit(".quad #{val.glabel}")
507
+ else
508
+ v, base = IntEvaluator.eval(val)
509
+ if !base
510
+ emit(".quad %u", v)
511
+ return
512
+ end
513
+ ty = base.ty
514
+ if (base.kind == AST::CONV) || (base.kind == AST::ADDR)
515
+ base = base.operand
516
+ end
517
+ if base.kind != AST::GVAR
518
+ raise "global variable expected, but got #{base}"
519
+ end
520
+ Util.assert!{ !ty.ptr.nil? }
521
+ emit(".quad #{base.glabel}+#{v * ty.ptr.size}")
522
+ end
523
+ else
524
+ raise "don't know how to handle\n <#{ty}>\n <#{val}>"
525
+ end
526
+ end
527
+
528
+ # @param [Node] operand
529
+ # @param [Integer] depth
530
+ def emit_data_addr(operand, depth)
531
+ case operand.kind
532
+ when AST::LVAR
533
+ label = @label_gen.next
534
+ emit(".data %d", depth + 1)
535
+ emit_label(label)
536
+ do_emit_data(operand.lvarinit, operand.ty.size, 0, depth + 1)
537
+ emit(".data #{depth}")
538
+ emit(".quad #{label}")
539
+ return
540
+ when AST::GVAR
541
+ emit(".quad #{operand.glabel}")
542
+ return
543
+ else
544
+ raise "internal error"
545
+ # error("internal error");
546
+ end
547
+ end
548
+
549
+ # @param [String] s
550
+ # @param [Integer] depth
551
+ def emit_data_charptr(s, depth)
552
+ label = @label_gen.next
553
+ emit(".data #{depth + 1}")
554
+ emit_label(label)
555
+ emit(".string \"#{Util.quote_cstring(s)}\"")
556
+ emit(".data #{depth}")
557
+ emit(".quad #{label}")
558
+ end
559
+
560
+ # @param [Node] v
561
+ def emit_bss(v)
562
+ # TODO(south37) impl SAVE when necessary
563
+ # SAVE
564
+ emit(".data")
565
+ if !v.declvar.ty.isstatic
566
+ emit(".global #{v.declvar.glabel}")
567
+ end
568
+ emit(".lcomm #{v.declvar.glabel}, #{v.declvar.ty.size}")
569
+ end
570
+
571
+ # @param [Node] node
572
+ def emit_conv(node)
573
+ # TODO(south37) impl SAVE when necessary
574
+ # SAVE
575
+ emit_expr(node.operand)
576
+ emit_load_convert(node.ty, node.operand.ty)
577
+ end
578
+
579
+ # @param [Type] to
580
+ # @param [Type] from
581
+ def emit_load_convert(to, from)
582
+ # TODO(south37) impl SAVE when necessary
583
+ # SAVE
584
+ if Type.is_inttype(from) && to.kind == Kind::FLOAT
585
+ emit("cvtsi2ss #eax, #xmm0")
586
+ elsif Type.is_inttype(from) && to.kind == Kind::DOUBLE
587
+ emit("cvtsi2sd #eax, #xmm0")
588
+ elsif from.kind == Kind::FLOAT && to.kind == Kind::DOUBLE
589
+ emit("cvtps2pd #xmm0, #xmm0")
590
+ elsif (from.kind == Kind::DOUBLE || from.kind == Kind::LDOUBLE) && (to.kind == Kind::FLOAT)
591
+ emit("cvtpd2ps #xmm0, #xmm0")
592
+ elsif to.kind == Kind::BOOL
593
+ emit_to_bool(from)
594
+ elsif Type.is_inttype(from) && Type.is_inttype(to)
595
+ emit_intcast(from)
596
+ elsif Type.is_inttype(to)
597
+ emit_toint(from)
598
+ end
599
+ end
600
+
601
+ # @param [Type] ty
602
+ def emit_intcast(ty)
603
+ case ty.kind
604
+ when Kind::BOOL, Kind::CHAR
605
+ ty.usig ? emit("movzbq #al, #rax") : emit("movsbq #al, #rax")
606
+ when Kind::SHORT
607
+ ty.usig ? emit("movzwq #ax, #rax") : emit("movswq #ax, #rax")
608
+ when Kind::INT
609
+ # cf. https://web.stanford.edu/class/cs107/guide/x86-64.html
610
+ ty.usig ? emit("mov #eax, #eax") : emit("cltq");
611
+ when Kind::LONG, Kind::LLONG
612
+ # Do nothing
613
+ end
614
+ end
615
+
616
+ # @param [Type] ty
617
+ def emit_to_bool(ty)
618
+ # TODO(south37) impl SAVE when necessary
619
+ # SAVE;
620
+ if Type.is_flotype(ty)
621
+ push_xmm(1)
622
+ emit("xorpd #xmm1, #xmm1")
623
+ emit("%s #xmm1, #xmm0", (ty.kind == Kind::FLOAT) ? "ucomiss" : "ucomisd")
624
+ emit("setne #al")
625
+ pop_xmm(1)
626
+ else
627
+ emit("cmp $0, #rax")
628
+ emit("setne #al")
629
+ end
630
+ emit("movzb #al, #eax")
631
+ end
632
+
633
+ # @param [Type] ty
634
+ def emit_toint(ty)
635
+ # TODO(south37) impl SAVE when necessary
636
+ # SAVE
637
+ if ty.kind == Kind::FLOAT
638
+ emit("cvttss2si #xmm0, #eax")
639
+ elsif ty.kind == Kind::DOUBLE
640
+ emit("cvttsd2si #xmm0, #eax")
641
+ end
642
+ end
643
+
644
+ # @param [Node] node
645
+ def emit_return(node)
646
+ # TODO(south37) impl SAVE when necessary
647
+ # SAVE
648
+ if node.retval
649
+ emit_expr(node.retval)
650
+ maybe_booleanize_retval(node.retval.ty)
651
+ end
652
+ emit_ret
653
+ end
654
+
655
+ # @param [Type] ty
656
+ def maybe_booleanize_retval(ty)
657
+ if ty.kind == Kind::BOOL
658
+ emit("movzx #al, #rax")
659
+ end
660
+ end
661
+
662
+ def emit_ret
663
+ # TODO(south37) impl SAVE when necessary
664
+ # SAVE
665
+ emit("leave")
666
+ emit("ret")
667
+ end
668
+
669
+ # @param [Node] node
670
+ def emit_compound_stmt(node)
671
+ # TODO(south37) impl SAVE when necessary
672
+ # SAVE
673
+ node.stmts.each do |stmt|
674
+ emit_expr(stmt)
675
+ end
676
+ end
677
+
678
+ # @param [Node] node
679
+ def emit_computed_goto(node)
680
+ # TODO(south37) impl SAVE when necessary
681
+ # SAVE;
682
+ emit_expr(node.operand)
683
+ emit("jmp *#rax")
684
+ end
685
+
686
+ # @param [Node]
687
+ def emit_binop(node)
688
+ # TODO(south37) impl SAVE when necessary
689
+ # SAVE
690
+ if node.ty.kind == Kind::PTR
691
+ emit_pointer_arith(node.kind, node.left, node.right)
692
+ return
693
+ end
694
+
695
+ case node.kind
696
+ when '<' then emit_comp("setl", "setb", node); return
697
+ when OP::EQ then emit_comp("sete", "sete", node); return
698
+ when OP::LE then emit_comp("setle", "setna", node); return
699
+ when OP::NE then emit_comp("setne", "setne", node); return
700
+ end
701
+
702
+ if Type.is_inttype(node.ty)
703
+ emit_binop_int_arith(node)
704
+ elsif Type.is_flotype(node.ty)
705
+ emit_binop_float_arith(node)
706
+ else
707
+ raise "internal error: #{node}"
708
+ end
709
+ end
710
+
711
+ # @param [AST] kind
712
+ # @param [Node] left
713
+ # @param [Node] right
714
+ def emit_pointer_arith(kind, left, right)
715
+ # TODO(south37) impl SAVE when necessary
716
+ # SAVE
717
+ emit_expr(left)
718
+ push("rcx")
719
+ push("rax")
720
+ emit_expr(right)
721
+ size = left.ty.ptr.size
722
+ if size > 1
723
+ emit("imul $#{size}, #rax")
724
+ end
725
+ emit("mov #rax, #rcx")
726
+ pop("rax")
727
+ case kind
728
+ when '+' then emit("add #rcx, #rax")
729
+ when '-' then emit("sub #rcx, #rax")
730
+ else
731
+ raise "invalid operator '#{kind}'"
732
+ # error("invalid operator '%d'", kind)
733
+ end
734
+ pop("rcx")
735
+ end
736
+
737
+ # @param [Node] node
738
+ def emit_binop_int_arith(node)
739
+ # TODO(south37) impl SAVE when necessary
740
+ # SAVE
741
+ case node.kind
742
+ when '+' then op = "add"
743
+ when '-' then op = "sub"
744
+ when '*' then op = "imul"
745
+ when '^' then op = "xor"
746
+ when OP::SAL then op = "sal"
747
+ when OP::SAR then op = "sar"
748
+ when OP::SHR then op = "shr"
749
+ when '/', '%'
750
+ # Do nothing
751
+ else
752
+ raise "invalid operator '#{node.kind}'"
753
+ end
754
+
755
+ emit_expr(node.left)
756
+ push("rax")
757
+ emit_expr(node.right)
758
+ emit("mov #rax, #rcx")
759
+ pop("rax")
760
+
761
+ if (node.kind == '/') || (node.kind == '%')
762
+ if node.ty.usig
763
+ emit("xor #edx, #edx");
764
+ emit("div #rcx");
765
+ else
766
+ emit("cqto");
767
+ emit("idiv #rcx")
768
+ end
769
+ if node.kind == '%'
770
+ emit("mov #edx, #eax")
771
+ end
772
+ elsif (node.kind == OP::SAL) || (node.kind == OP::SAR) || (node.kind == OP::SHR)
773
+ emit("#{op} #cl, ##{get_int_reg(node.left.ty, 'a')}")
774
+ else
775
+ emit("#{op} #rcx, #rax")
776
+ end
777
+ end
778
+
779
+ # @param [Node] node
780
+ def emit_binop_float_arith(node)
781
+ # TODO(south37) impl SAVE when necessary
782
+ # SAVE
783
+ isdouble = node.ty.kind == Kind::DOUBLE
784
+ case node.kind
785
+ when '+' then op = (isdouble ? "addsd" : "addss")
786
+ when '-' then op = (isdouble ? "subsd" : "subss")
787
+ when '*' then op = (isdouble ? "mulsd" : "mulss")
788
+ when '/' then op = (isdouble ? "divsd" : "divss")
789
+ else
790
+ raise "invalid operator '#{node.kind}'"
791
+ end
792
+
793
+ emit_expr(node.left)
794
+ push_xmm(0)
795
+ emit_expr(node.right)
796
+ emit("#{(isdouble ? "movsd" : "movss")} #xmm0, #xmm1")
797
+ pop_xmm(0);
798
+ emit("#{op} #xmm1, #xmm0")
799
+ end
800
+
801
+ # @param [Node] node
802
+ def emit_decl(node)
803
+ # TODO(south37) impl SAVE when necessary
804
+ # SAVE;
805
+ return if (!node.declinit)
806
+ emit_decl_init(node.declinit, node.declvar.loff, node.declvar.ty.size)
807
+ end
808
+
809
+ # @param [Array] inits
810
+ # @param [Integer] off
811
+ # @param [Integer] totalsize
812
+ def emit_decl_init(inits, off, totalsize)
813
+ emit_fill_holes(inits, off, totalsize)
814
+ inits.each do |node|
815
+ Util.assert!{ node.kind == AST::INIT }
816
+ isbitfield = (node.totype.bitsize && node.totype.bitsize > 0)
817
+ if node.initval.kind == AST::LITERAL && !isbitfield
818
+ emit_save_literal(node.initval, node.totype, node.initoff + off)
819
+ else
820
+ emit_expr(node.initval)
821
+ emit_lsave(node.totype, node.initoff + off)
822
+ end
823
+ end
824
+ end
825
+
826
+ # @param [Array] inits
827
+ # @param [Integer] off
828
+ # @param [Integer] totalsize
829
+ def emit_fill_holes(inits, off, totalsize)
830
+ # If at least one of the fields in a variable are initialized,
831
+ # unspecified fields has to be initialized with 0.
832
+ lastend = 0
833
+ inits.sort_by(&:initoff).each do |node|
834
+ if lastend < node.initoff
835
+ emit_zero_filler(lastend + off, node.initoff + off)
836
+ end
837
+ lastend = node.initoff + node.totype.size
838
+ end
839
+ emit_zero_filler(lastend + off, totalsize + off)
840
+ end
841
+
842
+ # @param [Integer] s
843
+ # @param [Integer] e
844
+ def emit_zero_filler(s, e)
845
+ # TODO(south37) impl SAVE when necessary
846
+ # SAVE;
847
+ while s <= (e- 4) do
848
+ emit("movl $0, #{s}(#rbp)")
849
+ s += 4
850
+ end
851
+ while s < e
852
+ emit("movb $0, #{s}(#rbp)")
853
+ s += 1
854
+ end
855
+ end
856
+
857
+ # @param [Node] node
858
+ # @param [Type] totype
859
+ # @param [Integer] off
860
+ def emit_save_literal(node, totype, off)
861
+ case totype.kind
862
+ when Kind::BOOL then emit("movb $#{node.ival}, #{off}(#rbp)")
863
+ when Kind::CHAR then emit("movb $#{node.ival}, #{off}(#rbp)")
864
+ when Kind::SHORT then emit("movw $#{node.ival}, #{off}(#rbp)")
865
+ when Kind::INT then emit("movl $#{node.ival}, #{off}(#rbp)")
866
+ when Kind::LONG, Kind::LLONG, Kind::PTR
867
+ emit("movl $#{node.ival & ((1 << 32) - 1)}, #{off }(#rbp)")
868
+ emit("movl $#{node.ival >> 32 }, #{off + 4}(#rbp)")
869
+ when Kind::FLOAT
870
+ val = [node.fval].pack('f').unpack('I')[0]
871
+ emit("movl $#{val}, #{off}(#rbp)")
872
+ when Kind::DOUBLE, Kind::LDOUBLE
873
+ val = [node.fval].pack('d').unpack('Q')[0]
874
+ emit("movl $#{val & ((1 << 32) - 1)}, #{off }(#rbp)")
875
+ emit("movl $#{val >> 32 }, #{off + 4}(#rbp)")
876
+ else
877
+ raise "internal error: <#{node}> <#{totype}> <#{off}>"
878
+ end
879
+ end
880
+
881
+ # @param [Type] ty
882
+ # @param [Integer] off
883
+ def emit_lsave(ty, off)
884
+ # TODO(south37) impl SAVE when necessary
885
+ # SAVE;
886
+ if ty.kind == Kind::FLOAT
887
+ emit("movss #xmm0, #{off}(#rbp)")
888
+ elsif ty.kind == Kind::DOUBLE
889
+ emit("movsd #xmm0, #{off}(#rbp)")
890
+ else
891
+ maybe_convert_bool(ty)
892
+ addr = "#{off}(%rbp)"
893
+ maybe_emit_bitshift_save(ty, addr)
894
+ reg = get_int_reg(ty, 'a')
895
+ emit("mov ##{reg}, %s", addr)
896
+ end
897
+ end
898
+
899
+ # @param [String] varname
900
+ # @param [Type] ty
901
+ # @param [Integer] off
902
+ def emit_gsave(varname, ty, off)
903
+ # TODO(south37) impl SAVE when necessary
904
+ # SAVE;
905
+ Util.assert!{ ty.kind != Kind::ARRAY }
906
+ maybe_convert_bool(ty)
907
+ reg = get_int_reg(ty, 'a')
908
+ addr = "#{varname}+#{off}(%rip)"
909
+ maybe_emit_bitshift_save(ty, addr)
910
+ emit("mov ##{reg}, %s", addr)
911
+ end
912
+
913
+ # @param [Type] ty
914
+ def maybe_convert_bool(ty)
915
+ if ty.kind == Kind::BOOL
916
+ emit("test #rax, #rax")
917
+ emit("setne #al")
918
+ end
919
+ end
920
+
921
+ # @param [Type] ty
922
+ # @param [Char] r
923
+ # @return [Integer]
924
+ def get_int_reg(ty, r)
925
+ Util.assert!{ r == 'a' || r == 'c' }
926
+ case ty.size
927
+ when 1 then return (r == 'a') ? "al" : "cl"
928
+ when 2 then return (r == 'a') ? "ax" : "cx"
929
+ when 4 then return (r == 'a') ? "eax" : "ecx"
930
+ when 8 then return (r == 'a') ? "rax" : "rcx"
931
+ else
932
+ raise "Unknown data size: #{ty}: #{ty.size}"
933
+ end
934
+ end
935
+
936
+ # @param [Type] ty
937
+ # @param [String] addr
938
+ def maybe_emit_bitshift_save(ty, addr)
939
+ # TODO(south37) impl SAVE when necessary
940
+ # SAVE;
941
+ return if ty.bitsize.nil? || ty.bitsize < 0
942
+ push("rcx")
943
+ push("rdi")
944
+ v = (1 << ty.bitsize) - 1
945
+ emit("mov $#{sprintf("%#x", v)}, #rdi")
946
+ emit("and #rdi, #rax")
947
+ emit("shl $#{ty.bitoff}, #rax")
948
+ emit("mov %s, ##{get_int_reg(ty, 'c')}", addr)
949
+ # TODO(south37): Consider bit size. Use 32 bit temporary here
950
+ v = 0xffffffff - (((1 << ty.bitsize) - 1) << ty.bitoff)
951
+ #v = ~(((1 << ty.bitsize) - 1) << ty.bitoff)
952
+ emit("mov $#{sprintf("%#x", v)}, #rdi")
953
+ emit("and #rdi, #rcx")
954
+ emit("or #rcx, #rax")
955
+ pop("rdi")
956
+ pop("rcx")
957
+ end
958
+
959
+ # @param [Node] node
960
+ def emit_assign(node)
961
+ # TODO(south37) impl SAVE when necessary
962
+ # SAVE;
963
+ if (node.left.ty.kind == Kind::STRUCT) && (node.left.ty.size > 8)
964
+ emit_copy_struct(node.left, node.right)
965
+ else
966
+ emit_expr(node.right)
967
+ emit_load_convert(node.ty, node.right.ty)
968
+ emit_store(node.left)
969
+ end
970
+ end
971
+
972
+ # @param [Node] node
973
+ def emit_label_addr(node)
974
+ # TODO(south37) impl SAVE when necessary
975
+ # SAVE;
976
+ emit("mov $%s, #rax", node.newlabel)
977
+ end
978
+
979
+ # @param [Node] left
980
+ # @param [Node] right
981
+ def emit_copy_struct(left, right)
982
+ push("rcx")
983
+ push("r11")
984
+ emit_addr(right)
985
+ emit("mov #rax, #rcx")
986
+ emit_addr(left)
987
+ i = 0
988
+ while (i < left.ty.size) do
989
+ emit("movq #{i}(#rcx), #r11")
990
+ emit("movq #r11, #{i}(#rax)")
991
+ i += 8
992
+ end
993
+ while (i < left.ty.size) do
994
+ emit("movl #{i}(#rcx), #r11")
995
+ emit("movl #r11, #{i}(#rax)")
996
+ i += 4
997
+ end
998
+ while (i < left.ty.size) do
999
+ emit("movb #{i}(#rcx), #r11")
1000
+ emit("movb #r11, #{i}(#rax)")
1001
+ i += 1
1002
+ end
1003
+ pop("r11")
1004
+ pop("rcx")
1005
+ end
1006
+
1007
+ # @param [Node] node
1008
+ def emit_addr(node)
1009
+ case node.kind
1010
+ when AST::LVAR
1011
+ ensure_lvar_init(node)
1012
+ emit("lea #{node.loff}(#rbp), #rax")
1013
+ when AST::GVAR
1014
+ emit("lea #{node.glabel}(#rip), #rax")
1015
+ when AST::DEREF
1016
+ emit_expr(node.operand)
1017
+ when AST::STRUCT_REF
1018
+ emit_addr(node.struct)
1019
+ emit("add $#{node.ty.offset}, #rax")
1020
+ when AST::FUNCDESG
1021
+ emit("lea #{node.fname}(#rip), #rax")
1022
+ else
1023
+ raise "internal error: #{node}"
1024
+ end
1025
+ end
1026
+
1027
+ # @param [Node] var
1028
+ def emit_store(var)
1029
+ # TODO(south37) impl SAVE when necessary
1030
+ # SAVE;
1031
+ case var.kind
1032
+ when AST::DEREF
1033
+ emit_assign_deref(var)
1034
+ when AST::STRUCT_REF
1035
+ emit_assign_struct_ref(var.struct, var.ty, 0)
1036
+ when AST::LVAR
1037
+ ensure_lvar_init(var)
1038
+ emit_lsave(var.ty, var.loff)
1039
+ when AST::GVAR
1040
+ emit_gsave(var.glabel, var.ty, 0)
1041
+ else
1042
+ raise "internal error"
1043
+ end
1044
+ end
1045
+
1046
+ # @param [Node] var
1047
+ def emit_assign_deref(var)
1048
+ # TODO(south37) impl SAVE when necessary
1049
+ # SAVE;
1050
+ push("rax")
1051
+ emit_expr(var.operand)
1052
+ do_emit_assign_deref(var.operand.ty.ptr, 0)
1053
+ end
1054
+
1055
+ # @param [Type] ty
1056
+ # @param [Integer] off
1057
+ def do_emit_assign_deref(ty, off)
1058
+ # TODO(south37) impl SAVE when necessary
1059
+ # SAVE;
1060
+ emit("mov (#rsp), #rcx")
1061
+ reg = get_int_reg(ty, 'c')
1062
+ if off > 0
1063
+ emit("mov ##{reg}, #{off}(#rax)")
1064
+ else
1065
+ emit("mov ##{reg}, (#rax)")
1066
+ end
1067
+ pop("rax")
1068
+ end
1069
+
1070
+ # @param [Node] struct
1071
+ # @param [Type] field
1072
+ # @param [Integer] off
1073
+ def emit_assign_struct_ref(struct, field, off)
1074
+ # TODO(south37) impl SAVE when necessary
1075
+ # SAVE;
1076
+ case struct.kind
1077
+ when AST::LVAR
1078
+ ensure_lvar_init(struct)
1079
+ emit_lsave(field, struct.loff + field.offset + off)
1080
+ when AST::GVAR
1081
+ emit_gsave(struct.glabel, field, field.offset + off)
1082
+ when AST::STRUCT_REF
1083
+ emit_assign_struct_ref(struct.struct, field, off + struct.ty.offset)
1084
+ when AST::DEREF
1085
+ push("rax")
1086
+ emit_expr(struct.operand)
1087
+ do_emit_assign_deref(field, field.offset + off)
1088
+ else
1089
+ raise "internal error: #{struct}"
1090
+ # error("internal error: %s", node2s(struct));
1091
+ end
1092
+ end
1093
+
1094
+ # @param [Node] node
1095
+ def ensure_lvar_init(node)
1096
+ # TODO(south37) impl SAVE when necessary
1097
+ # SAVE;
1098
+ Util.assert!{ node.kind == AST::LVAR }
1099
+ if node.lvarinit
1100
+ emit_decl_init(node.lvarinit, node.loff, node.ty.size)
1101
+ end
1102
+ node.lvarinit = nil
1103
+ end
1104
+
1105
+ # @param [Node] node
1106
+ def emit_deref(node)
1107
+ # TODO(south37) impl SAVE when necessary
1108
+ # SAVE;
1109
+ emit_expr(node.operand)
1110
+ emit_lload(node.operand.ty.ptr, "rax", 0)
1111
+ emit_load_convert(node.ty, node.operand.ty.ptr)
1112
+ end
1113
+
1114
+ # @param [Type] ty
1115
+ # @param [String] base
1116
+ # @param [Integer] off
1117
+ def emit_lload(ty, base, off)
1118
+ # TODO(south37) impl SAVE when necessary
1119
+ # SAVE;
1120
+ if ty.kind == Kind::ARRAY
1121
+ emit("lea #{off}(##{base}), #rax")
1122
+ elsif ty.kind == Kind::FLOAT
1123
+ emit("movss #{off}(##{base}), #xmm0")
1124
+ elsif (ty.kind == Kind::DOUBLE) || (ty.kind == Kind::LDOUBLE)
1125
+ emit("movsd %d(#%s), #xmm0", off, base)
1126
+ else
1127
+ inst = get_load_inst(ty)
1128
+ emit("#{inst} #{off}(##{base}), #rax")
1129
+ maybe_emit_bitshift_load(ty)
1130
+ end
1131
+ end
1132
+
1133
+ # @param [Type] ty
1134
+ def get_load_inst(ty)
1135
+ case ty.size
1136
+ when 1 then return "movsbq"
1137
+ when 2 then return "movswq"
1138
+ when 4 then return "movslq"
1139
+ when 8 then return "mov"
1140
+ else
1141
+ raise "Unknown data size: #{ty}: #{ty.size}"
1142
+ end
1143
+ end
1144
+
1145
+ # @param [Type] ty
1146
+ def maybe_emit_bitshift_load(ty)
1147
+ # TODO(south37) impl SAVE when necessary
1148
+ # SAVE;
1149
+ return if ty.bitsize.nil? || ty.bitsize <= 0
1150
+ emit("shr $#{ty.bitoff}, #rax")
1151
+ push("rcx")
1152
+ emit("mov $#{sprintf("%#x", (1 << ty.bitsize) - 1)}, #rcx")
1153
+ emit("and #rcx, #rax")
1154
+ pop("rcx")
1155
+ end
1156
+
1157
+ # @param [Node] node
1158
+ def emit_ternary(node)
1159
+ # TODO(south37) impl SAVE when necessary
1160
+ # SAVE;
1161
+ emit_expr(node.cond)
1162
+ ne = @label_gen.next
1163
+ emit_je(ne)
1164
+ if node.thn
1165
+ emit_expr(node.thn)
1166
+ end
1167
+ if node.els
1168
+ e = @label_gen.next
1169
+ emit_jmp(e)
1170
+ emit_label(ne)
1171
+ emit_expr(node.els)
1172
+ emit_label(e)
1173
+ else
1174
+ emit_label(ne)
1175
+ end
1176
+ end
1177
+
1178
+ # @param [String] label
1179
+ def emit_je(label)
1180
+ emit("test #rax, #rax")
1181
+ emit("je #{label}")
1182
+ end
1183
+
1184
+ # @param [String] label
1185
+ def emit_jmp(label)
1186
+ emit("jmp #{label}")
1187
+ end
1188
+
1189
+ # @param [Node] node
1190
+ def emit_goto(node)
1191
+ # TODO(south37) impl SAVE when necessary
1192
+ # SAVE;
1193
+ Util.assert!{ node.newlabel }
1194
+ emit_jmp(node.newlabel)
1195
+ end
1196
+
1197
+ # @param [Node] node
1198
+ # @return [Boolean]
1199
+ def maybe_emit_builtin(node)
1200
+ # TODO(south37) impl SAVE when necessary
1201
+ # SAVE;
1202
+ if "__builtin_return_address" == node.fname
1203
+ emit_builtin_return_address(node)
1204
+ return true
1205
+ end
1206
+ if "__builtin_reg_class" == node.fname
1207
+ emit_builtin_reg_class(node)
1208
+ return true
1209
+ end
1210
+ if "__builtin_va_start" == node.fname
1211
+ emit_builtin_va_start(node)
1212
+ return true
1213
+ end
1214
+ false
1215
+ end
1216
+
1217
+ # @param [Node] node
1218
+ def emit_builtin_return_address(node)
1219
+ push("r11");
1220
+ Util.assert!{ node.args.size == 1 }
1221
+ emit_expr(node.args[0])
1222
+ l = @label_gen.next
1223
+ e = @label_gen.next
1224
+ emit("mov #rbp, #r11")
1225
+ emit_label(l)
1226
+ emit("test #rax, #rax")
1227
+ emit("jz %s", e)
1228
+ emit("mov (#r11), #r11")
1229
+ emit("sub $1, #rax")
1230
+ emit_jmp(l)
1231
+ emit_label(e)
1232
+ emit("mov 8(#r11), #rax")
1233
+ pop("r11")
1234
+ end
1235
+
1236
+ # Set the register class for parameter passing to RAX.
1237
+ # 0 is INTEGER, 1 is SSE, 2 is MEMORY.
1238
+ #
1239
+ # @param [Node] node
1240
+ def emit_builtin_reg_class(node)
1241
+ arg = node.args[0]
1242
+ Util.assert!{ arg.ty.kind == Kind::PTR }
1243
+ ty = arg.ty.ptr
1244
+ if ty.kind == Kind::STRUCT
1245
+ emit("mov $2, #eax")
1246
+ elsif Type.is_flotype(ty)
1247
+ emit("mov $1, #eax")
1248
+ else
1249
+ emit("mov $0, #eax")
1250
+ end
1251
+ end
1252
+
1253
+ # @param [Node] node
1254
+ def emit_builtin_va_start(node)
1255
+ # TODO(south37) impl SAVE when necessary
1256
+ # SAVE;
1257
+ Util.assert!{ node.args.size == 1 }
1258
+ emit_expr(node.args[0])
1259
+ push("rcx")
1260
+ emit("movl $%d, (#rax)", @numgp * 8)
1261
+ emit("movl $%d, 4(#rax)", 48 + @numfp * 16)
1262
+ emit("lea %d(#rbp), #rcx", -REGAREA_SIZE)
1263
+ emit("mov #rcx, 16(#rax)")
1264
+ pop("rcx")
1265
+ end
1266
+
1267
+ # Functions in shared library
1268
+ # TODO(sout37) Fix this dirty hack.
1269
+ SHARED_LIBRARY_FUNCTIONS = ["printf", "calloc"]
1270
+
1271
+ # @param [Node] node
1272
+ def emit_func_call(node)
1273
+ # TODO(south37) impl SAVE when necessary
1274
+ # SAVE;
1275
+ opos = @stackpos
1276
+ isptr = (node.kind == AST::FUNCPTR_CALL)
1277
+ ftype = isptr ? node.fptr.ty.ptr : node.ftype
1278
+
1279
+ ints = []
1280
+ floats = []
1281
+ rest = []
1282
+ classify_args(ints, floats, rest, node.args)
1283
+ save_arg_regs(ints.size, floats.size)
1284
+
1285
+ padding = @stackpos % 16
1286
+ if (padding > 0)
1287
+ emit("sub $8, #rsp")
1288
+ @stackpos += 8
1289
+ end
1290
+
1291
+ restsize = emit_args(rest.reverse)
1292
+ if isptr
1293
+ emit_expr(node.fptr)
1294
+ push("rax")
1295
+ end
1296
+ emit_args(ints)
1297
+ emit_args(floats)
1298
+ pop_float_args(floats.size)
1299
+ pop_int_args(ints.size)
1300
+
1301
+ if isptr
1302
+ pop("r11")
1303
+ end
1304
+ if ftype.hasva
1305
+ emit("mov $#{floats.size}, #eax")
1306
+ end
1307
+
1308
+ if isptr
1309
+ emit("call *#r11")
1310
+ else
1311
+ fname = node.fname
1312
+ # Add `@PLT` suffix to functions in shared library here.
1313
+ if SHARED_LIBRARY_FUNCTIONS.include?(fname)
1314
+ fname += "@PLT"
1315
+ end
1316
+ emit("call #{fname}")
1317
+ end
1318
+ maybe_booleanize_retval(node.ty)
1319
+ if restsize > 0
1320
+ emit("add $#{restsize}, #rsp")
1321
+ @stackpos -= restsize
1322
+ end
1323
+ if padding > 0
1324
+ emit("add $8, #rsp")
1325
+ @stackpos -= 8
1326
+ end
1327
+ restore_arg_regs(ints.size, floats.size)
1328
+ Util.assert!{ opos == @stackpos }
1329
+ end
1330
+
1331
+ # @param(return) [Array] ints
1332
+ # @param(return) [Array] floats
1333
+ # @param(return) [Array] rest
1334
+ # @param [Array] args
1335
+ def classify_args(ints, floats, rest, args)
1336
+ # TODO(south37) impl SAVE when necessary
1337
+ # SAVE;
1338
+ ireg = 0
1339
+ xreg = 0
1340
+ imax = 6
1341
+ xmax = 8
1342
+ args.each do |v|
1343
+ if v.ty.kind == Kind::STRUCT
1344
+ rest.push(v)
1345
+ elsif Type.is_flotype(v.ty)
1346
+ if xreg < xmax
1347
+ floats.push(v)
1348
+ else
1349
+ rest.push(v)
1350
+ end
1351
+ xreg += 1
1352
+ else
1353
+ if ireg < imax
1354
+ ints.push(v)
1355
+ else
1356
+ rest.push(v)
1357
+ end
1358
+ ireg += 1
1359
+ end
1360
+ end
1361
+ end
1362
+
1363
+ # @param [Integer] nints
1364
+ # @param [Integer] nfloats
1365
+ def save_arg_regs(nints, nfloats)
1366
+ # TODO(south37) impl SAVE when necessary
1367
+ # SAVE;
1368
+ Util.assert!{ nints <= 6 }
1369
+ Util.assert!{ nfloats <= 8 }
1370
+ 0.upto(nints - 1) do |i|
1371
+ push(REGS[i])
1372
+ end
1373
+ 1.upto(nfloats - 1) do |i|
1374
+ push_xmm(i)
1375
+ end
1376
+ end
1377
+
1378
+ # @param [Integer] nints
1379
+ # @param [Integer] nfloats
1380
+ def restore_arg_regs(nints, nfloats)
1381
+ # TODO(south37) impl SAVE when necessary
1382
+ # SAVE;
1383
+ (nfloats - 1).downto(1) do |i|
1384
+ pop_xmm(i);
1385
+ end
1386
+ (nints - 1).downto(0) do |i|
1387
+ pop(REGS[i])
1388
+ end
1389
+ end
1390
+
1391
+ # @param [Array] vals
1392
+ # @return [Integer]
1393
+ def emit_args(vals)
1394
+ # TODO(south37) impl SAVE when necessary
1395
+ # SAVE;
1396
+ r = 0
1397
+ vals.each do |v|
1398
+ if v.ty.kind == Kind::STRUCT
1399
+ emit_addr(v);
1400
+ r += push_struct(v.ty.size)
1401
+ elsif Type.is_flotype(v.ty)
1402
+ emit_expr(v)
1403
+ push_xmm(0)
1404
+ r += 8
1405
+ else
1406
+ emit_expr(v)
1407
+ push("rax")
1408
+ r += 8
1409
+ end
1410
+ end
1411
+ r
1412
+ end
1413
+
1414
+ # @param [Integer] nints
1415
+ def pop_int_args(nints)
1416
+ # TODO(south37) impl SAVE when necessary
1417
+ # SAVE;
1418
+ (nints - 1).downto(0) do |i|
1419
+ pop(REGS[i]);
1420
+ end
1421
+ end
1422
+
1423
+ # @param [Integer] nfloats
1424
+ def pop_float_args(nfloats)
1425
+ # TODO(south37) impl SAVE when necessary
1426
+ # SAVE;
1427
+ (nfloats - 1).downto(0) do |i|
1428
+ pop_xmm(i)
1429
+ end
1430
+ end
1431
+
1432
+ # @param [String] inst
1433
+ # @param [String] usiginst
1434
+ # @param [Node] node
1435
+ def emit_comp(inst, usiginst, node)
1436
+ # TODO(south37) impl SAVE when necessary
1437
+ # SAVE;
1438
+ if Type.is_flotype(node.left.ty)
1439
+ emit_expr(node.left)
1440
+ push_xmm(0)
1441
+ emit_expr(node.right)
1442
+ pop_xmm(1)
1443
+ if node.left.ty.kind == Kind::FLOAT
1444
+ emit("ucomiss #xmm0, #xmm1")
1445
+ else
1446
+ emit("ucomisd #xmm0, #xmm1")
1447
+ end
1448
+ else
1449
+ emit_expr(node.left)
1450
+ push("rax")
1451
+ emit_expr(node.right)
1452
+ pop("rcx")
1453
+ kind = node.left.ty.kind
1454
+ if (kind == Kind::LONG) || (kind == Kind::LLONG)
1455
+ emit("cmp #rax, #rcx")
1456
+ else
1457
+ emit("cmp #eax, #ecx")
1458
+ end
1459
+ end
1460
+ if Type.is_flotype(node.left.ty) || node.left.ty.usig
1461
+ emit("#{usiginst} #al")
1462
+ else
1463
+ emit("#{inst} #al")
1464
+ end
1465
+ emit("movzb #al, #eax")
1466
+ end
1467
+
1468
+ # @param [Node] node
1469
+ # @param [String] op
1470
+ def emit_pre_inc_dec(node, op)
1471
+ # TODO(south37) impl SAVE when necessary
1472
+ # SAVE;
1473
+ emit_expr(node.operand)
1474
+ emit("#{op} $#{node.ty.ptr ? node.ty.ptr.size : 1}, #rax")
1475
+ emit_store(node.operand)
1476
+ end
1477
+
1478
+ # @param [Node] node
1479
+ # @param [String] op
1480
+ def emit_post_inc_dec(node, op)
1481
+ # TODO(south37) impl SAVE when necessary
1482
+ # SAVE;
1483
+ emit_expr(node.operand)
1484
+ push("rax")
1485
+ emit("#{op} $#{node.ty.ptr ? node.ty.ptr.size : 1}, #rax")
1486
+ emit_store(node.operand)
1487
+ pop("rax")
1488
+ end
1489
+
1490
+ # @param [Node] node
1491
+ def emit_lognot(node)
1492
+ # TODO(south37) impl SAVE when necessary
1493
+ # SAVE;
1494
+ emit_expr(node.operand)
1495
+ emit("cmp $0, #rax")
1496
+ emit("sete #al")
1497
+ emit("movzb #al, #eax")
1498
+ end
1499
+
1500
+ # @param [Node] node
1501
+ def emit_logand(node)
1502
+ # TODO(south37) impl SAVE when necessary
1503
+ # SAVE;
1504
+ e = @label_gen.next
1505
+ emit_expr(node.left)
1506
+ emit("test #rax, #rax")
1507
+ emit("mov $0, #rax")
1508
+ emit("je #{e}")
1509
+ emit_expr(node.right)
1510
+ emit("test #rax, #rax")
1511
+ emit("mov $0, #rax")
1512
+ emit("je #{e}")
1513
+ emit("mov $1, #rax")
1514
+ emit_label(e)
1515
+ end
1516
+
1517
+ # @param [Node] node
1518
+ def emit_logor(node)
1519
+ # TODO(south37) impl SAVE when necessary
1520
+ # SAVE;
1521
+ e = @label_gen.next
1522
+ emit_expr(node.left)
1523
+ emit("test #rax, #rax")
1524
+ emit("mov $1, #rax")
1525
+ emit("jne #{e}")
1526
+ emit_expr(node.right)
1527
+ emit("test #rax, #rax")
1528
+ emit("mov $1, #rax")
1529
+ emit("jne #{e}")
1530
+ emit("mov $0, #rax")
1531
+ emit_label(e)
1532
+ end
1533
+
1534
+ # @param [Node] node
1535
+ def emit_cast(node)
1536
+ # TODO(south37) impl SAVE when necessary
1537
+ # SAVE;
1538
+ emit_expr(node.operand)
1539
+ emit_load_convert(node.ty, node.operand.ty)
1540
+ end
1541
+
1542
+ # @param [Node]
1543
+ def emit_bitand(node)
1544
+ # TODO(south37) impl SAVE when necessary
1545
+ # SAVE;
1546
+ emit_expr(node.left)
1547
+ push("rax")
1548
+ emit_expr(node.right)
1549
+ pop("rcx")
1550
+ emit("and #rcx, #rax")
1551
+ end
1552
+
1553
+ # @param [Node]
1554
+ def emit_bitor(node)
1555
+ # TODO(south37) impl SAVE when necessary
1556
+ # SAVE;
1557
+ emit_expr(node.left)
1558
+ push("rax")
1559
+ emit_expr(node.right)
1560
+ pop("rcx")
1561
+ emit("or #rcx, #rax")
1562
+ end
1563
+
1564
+ # @param [Node] node
1565
+ def emit_bitnot(node)
1566
+ # TODO(south37) impl SAVE when necessary
1567
+ # SAVE;
1568
+ emit_expr(node.operand)
1569
+ emit("not #rax")
1570
+ end
1571
+
1572
+ # @param [Node] struct
1573
+ # @param [Type] field
1574
+ # @param [Integer] off
1575
+ def emit_load_struct_ref(struct, field, off)
1576
+ # TODO(south37) impl SAVE when necessary
1577
+ # SAVE;
1578
+ case struct.kind
1579
+ when AST::LVAR
1580
+ ensure_lvar_init(struct)
1581
+ emit_lload(field, "rbp", struct.loff + field.offset + off)
1582
+ when AST::GVAR
1583
+ emit_gload(field, struct.glabel, field.offset + off)
1584
+ when AST::STRUCT_REF
1585
+ emit_load_struct_ref(struct.struct, field, struct.ty.offset + off)
1586
+ when AST::DEREF
1587
+ emit_expr(struct.operand)
1588
+ emit_lload(field, "rax", field.offset + off)
1589
+ else
1590
+ raise "internal error: #{struct}"
1591
+ end
1592
+ end
1593
+
1594
+ # @param [Node] node
1595
+ def emit_comma(node)
1596
+ # TODO(south37) impl SAVE when necessary
1597
+ # SAVE;
1598
+ emit_expr(node.left)
1599
+ emit_expr(node.right)
1600
+ end
1601
+ end
1602
+ end