kompiler 0.3.0.pre.2 → 0.3.0.pre.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kompiler/arch_manager.rb +1 -1
- data/lib/kompiler/architectures/armv8a/instructions.rb +12 -0
- data/lib/kompiler/compiler_functions.rb +116 -7
- data/lib/kompiler/parsers.rb +8 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d37e70a65615ea1b7aece9de1a2ae544a30d9f3f9f1f44d233fac8ecde023b63
|
4
|
+
data.tar.gz: 533a6ac4a19a03c8ca483c63bf454d4cda802943462ea23bcbc1a59688e64d8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad275ed1d7bbb7dad29409b3ca2f4e061c08f4534bf7c2104d2c20c235a1030e496ae6381322042fe1d1bdd699acc5e970ef82b521031853d4222792b6bf388f
|
7
|
+
data.tar.gz: 9132f9c232bc01ff2ebfac62bfa09527e79f644ce0d15a360de91ece0a854187da581b6e67c2bec78e6745845fb2257c759786d71e02d44f17fbf4919e7e106c
|
@@ -954,6 +954,18 @@ end
|
|
954
954
|
],
|
955
955
|
bitsize: 32
|
956
956
|
},
|
957
|
+
{
|
958
|
+
keyword: "svc",
|
959
|
+
name: "Supervisor Call",
|
960
|
+
description: "Triggers a synchronous exception taken to EL1, passing an immediate value to the ESR_ELx system register.",
|
961
|
+
operands: [{type: "immediate", name: "Immediate"}],
|
962
|
+
mc_constructor: [
|
963
|
+
["bits", 1,0, 0,0,0],
|
964
|
+
["get_bits", ["get_operand", 0], 0, 16],
|
965
|
+
["bits", 0,0,0, 0,0,1,0,1,0,1,1],
|
966
|
+
],
|
967
|
+
bitsize: 32
|
968
|
+
},
|
957
969
|
|
958
970
|
|
959
971
|
#
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module CompilerFunctions
|
7
7
|
|
8
8
|
def self.parse_includes(lines, loaded_files=[])
|
9
9
|
|
@@ -83,6 +83,113 @@ def self.parse_includes(lines, loaded_files=[])
|
|
83
83
|
end
|
84
84
|
|
85
85
|
|
86
|
+
def self.parse_macros(lines)
|
87
|
+
|
88
|
+
macros = []
|
89
|
+
|
90
|
+
line_i = 0
|
91
|
+
|
92
|
+
loop do
|
93
|
+
break if line_i >= lines.size
|
94
|
+
|
95
|
+
line = lines[line_i]
|
96
|
+
|
97
|
+
keyword, operands = Kompiler::Parsers.parse_instruction_line line
|
98
|
+
|
99
|
+
keyword = keyword[1..] if keyword.start_with? "."
|
100
|
+
|
101
|
+
if keyword == 'macro'
|
102
|
+
raise "Macro definition error: Expected two operands to be provided, while #{operands.size} were given" if operands.size != 2
|
103
|
+
raise "Macro definition error: The macro name must either be a word or a string" if !["label", "string"].include?(operands[0][:type])
|
104
|
+
|
105
|
+
case operands[0][:type]
|
106
|
+
when "label"
|
107
|
+
macro_name = operands[0][:value]
|
108
|
+
when "string"
|
109
|
+
macro_name = operands[0][:value]
|
110
|
+
end
|
111
|
+
|
112
|
+
macro_definition = operands[1][:definition]
|
113
|
+
|
114
|
+
macros << {name: macro_name, definition: macro_definition}
|
115
|
+
|
116
|
+
lines.delete_at line_i
|
117
|
+
else
|
118
|
+
line_i += 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Apply the macros to all lines, and then the lines that were changed, and than again, and so on (iterative loop until none of the lines need to be checked)
|
123
|
+
|
124
|
+
lines_to_check = (0...lines.size).to_a
|
125
|
+
|
126
|
+
while lines_to_check.size != 0 # Repeat until no more lines to check
|
127
|
+
|
128
|
+
# Define restricted separators characters (characters that CAN'T separate a macro from everything else)
|
129
|
+
restricted_separator_chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + ["_", "."]
|
130
|
+
|
131
|
+
# Create an array for the lines to check once again
|
132
|
+
new_lines_to_check = []
|
133
|
+
|
134
|
+
lines_to_check.each do |line_i|
|
135
|
+
line = lines[line_i]
|
136
|
+
|
137
|
+
char_i = 0
|
138
|
+
|
139
|
+
# Create a variable to indicate if a macro was used on the current line
|
140
|
+
line_macro_used = false
|
141
|
+
|
142
|
+
loop do
|
143
|
+
break if char_i >= line.size
|
144
|
+
|
145
|
+
if ['"', "'"].include? line[char_i]
|
146
|
+
# If a string, skip it
|
147
|
+
str, parsed_length = Kompiler::Parsers.parse_str line[char_i..]
|
148
|
+
char_i += parsed_length
|
149
|
+
next
|
150
|
+
end
|
151
|
+
|
152
|
+
cut_line = line[char_i..]
|
153
|
+
|
154
|
+
# Create a variable to indicate if a macro was used in the current position
|
155
|
+
macro_used = false
|
156
|
+
|
157
|
+
macros.each do |macro|
|
158
|
+
macro_name = macro[:name]
|
159
|
+
macro_def = macro[:definition]
|
160
|
+
next if !cut_line.start_with?(macro_name) # Skip if doesn't begin with the macro's name
|
161
|
+
next if (cut_line.size > macro_name.size) && restricted_separator_chars.include?(cut_line[macro_name.size]) # Skip if there is a character after the macro name, and the character is not permitted
|
162
|
+
next if (char_i > 0) && restricted_separator_chars.include?(line[char_i - 1]) # Skip if there is a character before the checking sequence, and the character is not permitted
|
163
|
+
|
164
|
+
# Here if the macro is 'accepted'
|
165
|
+
line = line[...char_i] + macro_def + line[(char_i + macro_name.size)..]
|
166
|
+
# Indicate that a macro was used
|
167
|
+
macro_used = true
|
168
|
+
end
|
169
|
+
|
170
|
+
if macro_used
|
171
|
+
# If a macro was used, indicate that on line level
|
172
|
+
line_macro_used = true
|
173
|
+
else
|
174
|
+
# If a macro wasn't used, proceed to the next character
|
175
|
+
char_i += 1
|
176
|
+
end
|
177
|
+
end # line characters loop
|
178
|
+
|
179
|
+
if line_macro_used
|
180
|
+
# If a macro was used on the current line, update the lines array, and add the line to check for macros again
|
181
|
+
lines[line_i] = line
|
182
|
+
new_lines_to_check << line_i
|
183
|
+
end
|
184
|
+
end # lines_to_check.each loop
|
185
|
+
|
186
|
+
lines_to_check = new_lines_to_check # Update lines to check with the new ones
|
187
|
+
|
188
|
+
end # while lines_to_check.size != 0 loop
|
189
|
+
|
190
|
+
lines
|
191
|
+
end
|
192
|
+
|
86
193
|
|
87
194
|
def self.parse_code(lines)
|
88
195
|
|
@@ -97,7 +204,7 @@ def self.parse_code(lines)
|
|
97
204
|
if !is_char_whitespace.include?(false) # If only whitespace
|
98
205
|
next # Skip
|
99
206
|
end
|
100
|
-
|
207
|
+
|
101
208
|
#
|
102
209
|
# Label definitions are now a directive, so this isn't needed
|
103
210
|
#
|
@@ -243,17 +350,19 @@ end
|
|
243
350
|
def self.compile(code, included_files=[])
|
244
351
|
|
245
352
|
lines = Kompiler::Parsers.get_code_lines(code)
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
353
|
+
|
354
|
+
included_lines = parse_includes(lines, included_files.map{|fname| File.expand_path(fname)})
|
355
|
+
|
356
|
+
macroed_lines = parse_macros(included_lines)
|
357
|
+
|
358
|
+
parsed_lines = parse_code(macroed_lines)
|
250
359
|
|
251
360
|
labels = get_labels(parsed_lines)
|
252
361
|
|
253
362
|
# machine_code_bit_lines = construct_program_mc(parsed_lines, labels)
|
254
363
|
#
|
255
364
|
# machine_code_bytes = bit_lines_to_bytes(machine_code_bit_lines)
|
256
|
-
|
365
|
+
|
257
366
|
machine_code_bytes = construct_program_mc(parsed_lines, labels)
|
258
367
|
end
|
259
368
|
|
data/lib/kompiler/parsers.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module Parsers
|
7
7
|
|
8
8
|
def self.parse_str(code)
|
9
9
|
|
@@ -195,7 +195,7 @@ def self.check_label_operand(str)
|
|
195
195
|
return false if ("0".."9").to_a.include?(str[0])
|
196
196
|
|
197
197
|
# Check if it's only made up of allowed characters
|
198
|
-
allowed_chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + ["_"]
|
198
|
+
allowed_chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + ["_", "."]
|
199
199
|
|
200
200
|
is_each_char_allowed = str.each_char.map{|c| allowed_chars.include?(c)}
|
201
201
|
|
@@ -366,10 +366,9 @@ end
|
|
366
366
|
|
367
367
|
# Returns array of [status, operands]
|
368
368
|
# If status = false, operands = nil; otherwise, status = true, operands = instruction operands
|
369
|
-
def self.
|
370
|
-
|
371
|
-
keyword, operands = parse_instruction_line(line)
|
369
|
+
def self.match_parsed_line_to_instruction(parsed_line, instruction)
|
372
370
|
|
371
|
+
keyword, operands = parsed_line
|
373
372
|
|
374
373
|
# Check if the keyword matches
|
375
374
|
if instruction[:keyword] != keyword
|
@@ -396,9 +395,12 @@ def self.check_instruction(line)
|
|
396
395
|
instruction = nil
|
397
396
|
operands = nil
|
398
397
|
|
398
|
+
parsed_line = Kompiler::Parsers.parse_instruction_line(line)
|
399
|
+
|
399
400
|
Kompiler::Architecture.instructions.each do |curr_instruction|
|
400
401
|
# If the instruction matches - break
|
401
|
-
|
402
|
+
|
403
|
+
status, curr_operands = match_parsed_line_to_instruction(parsed_line, curr_instruction)
|
402
404
|
if status == true
|
403
405
|
instruction = curr_instruction
|
404
406
|
operands = curr_operands
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kompiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0.pre.
|
4
|
+
version: 0.3.0.pre.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyryl Shyshko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Kompiler is a low-level, modular and extendable compiler for any architecture.
|
14
14
|
By default Kompiler supports ARMv8-a, but other architecture extensions can be downloaded
|