kompiler 0.3.0.pre.2 → 0.3.0.pre.3
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.
- 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
|