idlc 0.1.1
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 +7 -0
- data/LICENSE +26 -0
- data/bin/idlc +10 -0
- data/lib/idlc/ast.rb +9611 -0
- data/lib/idlc/ast_decl.rb +22 -0
- data/lib/idlc/cli.rb +232 -0
- data/lib/idlc/idl.treetop +675 -0
- data/lib/idlc/idl_parser.rb +15386 -0
- data/lib/idlc/interfaces.rb +135 -0
- data/lib/idlc/log.rb +23 -0
- data/lib/idlc/passes/find_referenced_csrs.rb +39 -0
- data/lib/idlc/passes/find_return_values.rb +76 -0
- data/lib/idlc/passes/find_src_registers.rb +125 -0
- data/lib/idlc/passes/gen_adoc.rb +355 -0
- data/lib/idlc/passes/gen_option_adoc.rb +169 -0
- data/lib/idlc/passes/prune.rb +957 -0
- data/lib/idlc/passes/reachable_exceptions.rb +206 -0
- data/lib/idlc/passes/reachable_functions.rb +221 -0
- data/lib/idlc/symbol_table.rb +549 -0
- data/lib/idlc/syntax_node.rb +64 -0
- data/lib/idlc/type.rb +992 -0
- data/lib/idlc/version.rb +10 -0
- data/lib/idlc.rb +409 -0
- metadata +394 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
3
|
+
|
|
4
|
+
# typed: strict
|
|
5
|
+
# frozen_string_literal: true
|
|
6
|
+
|
|
7
|
+
require "sorbet-runtime"
|
|
8
|
+
|
|
9
|
+
require_relative "type"
|
|
10
|
+
|
|
11
|
+
module Idl
|
|
12
|
+
# interface for a parameter that may only be known at runtime
|
|
13
|
+
module RuntimeParam
|
|
14
|
+
extend T::Sig
|
|
15
|
+
extend T::Helpers
|
|
16
|
+
interface!
|
|
17
|
+
|
|
18
|
+
include Kernel
|
|
19
|
+
|
|
20
|
+
ValueType =
|
|
21
|
+
T.type_alias { T.any(Integer, T::Boolean, String, T::Array[Integer], T::Array[Integer], T::Array[T::Boolean], T::Array[String]) }
|
|
22
|
+
|
|
23
|
+
sig { abstract.returns(String) }
|
|
24
|
+
def name; end
|
|
25
|
+
|
|
26
|
+
sig { abstract.returns(String) }
|
|
27
|
+
def description; end
|
|
28
|
+
|
|
29
|
+
sig { abstract.returns(Schema) }
|
|
30
|
+
def schema; end
|
|
31
|
+
|
|
32
|
+
sig { abstract.returns(T::Boolean) }
|
|
33
|
+
def value_known?; end
|
|
34
|
+
|
|
35
|
+
sig { abstract.returns(ValueType) }
|
|
36
|
+
def value; end
|
|
37
|
+
|
|
38
|
+
sig { abstract.returns(Type) }
|
|
39
|
+
def idl_type; end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# basic interface for objects that are described with JSON Schema
|
|
43
|
+
module Schema
|
|
44
|
+
extend T::Sig
|
|
45
|
+
extend T::Helpers
|
|
46
|
+
interface!
|
|
47
|
+
|
|
48
|
+
sig { abstract.returns(T::Boolean) }
|
|
49
|
+
def max_val_known?; end
|
|
50
|
+
|
|
51
|
+
sig { abstract.returns(Integer) }
|
|
52
|
+
def max_val; end
|
|
53
|
+
|
|
54
|
+
sig { abstract.returns(T::Boolean) }
|
|
55
|
+
def min_val_known?; end
|
|
56
|
+
|
|
57
|
+
sig { abstract.returns(Integer) }
|
|
58
|
+
def min_val; end
|
|
59
|
+
|
|
60
|
+
sig { abstract.returns(Type) }
|
|
61
|
+
def to_idl_type; end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module CsrField
|
|
65
|
+
extend T::Sig
|
|
66
|
+
extend T::Helpers
|
|
67
|
+
interface!
|
|
68
|
+
|
|
69
|
+
sig { abstract.returns(String) }
|
|
70
|
+
def name; end
|
|
71
|
+
|
|
72
|
+
# whether or not this field is defined in both RV32 and RV64
|
|
73
|
+
sig { abstract.returns(T::Boolean) }
|
|
74
|
+
def defined_in_all_bases?; end
|
|
75
|
+
|
|
76
|
+
sig { abstract.returns(T::Boolean) }
|
|
77
|
+
def defined_in_base32?; end
|
|
78
|
+
|
|
79
|
+
sig { abstract.returns(T::Boolean) }
|
|
80
|
+
def defined_in_base64?; end
|
|
81
|
+
|
|
82
|
+
# whether or not this field is defined only in RV64
|
|
83
|
+
sig { abstract.returns(T::Boolean) }
|
|
84
|
+
def base64_only?; end
|
|
85
|
+
|
|
86
|
+
# whether or not this field is defined only in RV32
|
|
87
|
+
sig { abstract.returns(T::Boolean) }
|
|
88
|
+
def base32_only?; end
|
|
89
|
+
|
|
90
|
+
# returns the location of the field in the CSR.
|
|
91
|
+
# base is required when the field moves locations between RV32 and RV64
|
|
92
|
+
sig { abstract.params(base: T.nilable(Integer)).returns(T::Range[Integer]) }
|
|
93
|
+
def location(base); end
|
|
94
|
+
|
|
95
|
+
sig { abstract.params(base: T.nilable(Integer)).returns(Integer) }
|
|
96
|
+
def width(base); end
|
|
97
|
+
|
|
98
|
+
sig { abstract.params(base: T.nilable(Integer)).returns(T.nilable(String)) }
|
|
99
|
+
def type(base); end
|
|
100
|
+
|
|
101
|
+
# whether or not the field is supposed to exist/be implemented in the
|
|
102
|
+
# execution context
|
|
103
|
+
sig { abstract.returns(T::Boolean) }
|
|
104
|
+
def exists?; end
|
|
105
|
+
|
|
106
|
+
sig { abstract.returns(ValueRbType) }
|
|
107
|
+
def reset_value; end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
module Csr
|
|
111
|
+
extend T::Sig
|
|
112
|
+
extend T::Helpers
|
|
113
|
+
interface!
|
|
114
|
+
|
|
115
|
+
sig { abstract.returns(String) }
|
|
116
|
+
def name; end
|
|
117
|
+
|
|
118
|
+
sig { abstract.params(base: T.nilable(Integer)).returns(T.nilable(Integer)) }
|
|
119
|
+
def length(base); end
|
|
120
|
+
|
|
121
|
+
sig { abstract.returns(Integer) }
|
|
122
|
+
def max_length; end
|
|
123
|
+
|
|
124
|
+
sig { abstract.returns(T::Boolean) }
|
|
125
|
+
def dynamic_length?; end
|
|
126
|
+
|
|
127
|
+
sig { abstract.returns(T::Array[CsrField]) }
|
|
128
|
+
def fields; end
|
|
129
|
+
|
|
130
|
+
# If the entire CSR is read-only with a known reset value, returns the value
|
|
131
|
+
# otherwise, returns nil
|
|
132
|
+
sig { abstract.returns(T.nilable(Integer)) }
|
|
133
|
+
def value; end
|
|
134
|
+
end
|
|
135
|
+
end
|
data/lib/idlc/log.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
3
|
+
|
|
4
|
+
# typed: true
|
|
5
|
+
# frozen_string_literal: true
|
|
6
|
+
|
|
7
|
+
require "logger"
|
|
8
|
+
|
|
9
|
+
require "sorbet-runtime"
|
|
10
|
+
|
|
11
|
+
module Idl
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
sig { returns(Logger).checked(:tests) }
|
|
15
|
+
def self.logger
|
|
16
|
+
@logger ||= Logger.new($stdout, level: :warn)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
sig { params(logger: Logger).returns(Logger) }
|
|
20
|
+
def self.set_logger(logger)
|
|
21
|
+
@logger = logger
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
3
|
+
|
|
4
|
+
# typed: true
|
|
5
|
+
# frozen_string_literal: true
|
|
6
|
+
|
|
7
|
+
require "sorbet-runtime"
|
|
8
|
+
|
|
9
|
+
module Idl
|
|
10
|
+
class AstNode
|
|
11
|
+
extend T::Sig
|
|
12
|
+
sig { overridable.returns(T::Array[String]) }
|
|
13
|
+
def find_referenced_csrs
|
|
14
|
+
csrs = T.let([], T::Array[String])
|
|
15
|
+
@children.each do |child|
|
|
16
|
+
csrs += child.find_referenced_csrs
|
|
17
|
+
end
|
|
18
|
+
csrs.uniq
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class CsrReadExpressionAst < AstNode
|
|
23
|
+
sig { override.returns(T::Array[String]) }
|
|
24
|
+
def find_referenced_csrs
|
|
25
|
+
[csr_name]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class CsrWriteAst < AstNode
|
|
30
|
+
sig { override.returns(T::Array[String]) }
|
|
31
|
+
def find_referenced_csrs
|
|
32
|
+
if idx.is_a?(IntLiteralAst)
|
|
33
|
+
[]
|
|
34
|
+
else
|
|
35
|
+
[idx.text_value]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
3
|
+
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
# pass to find all the possible return values from a function body
|
|
7
|
+
|
|
8
|
+
module Idl
|
|
9
|
+
|
|
10
|
+
class AstNode
|
|
11
|
+
def pass_find_return_values(values, current_conditions)
|
|
12
|
+
children.each do |c|
|
|
13
|
+
c.pass_find_return_values(values, current_conditions)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class ReturnStatementAst < AstNode
|
|
19
|
+
def pass_find_return_values(values, current_conditions, symtab)
|
|
20
|
+
# if the action is a ternary operator, there is another condition to consider
|
|
21
|
+
if first.is_a?(TernaryOperatorExpressionAst)
|
|
22
|
+
current_conditions.push first.condition
|
|
23
|
+
values << [first.true_expression, current_conditions.clone]
|
|
24
|
+
current_conditions.pop
|
|
25
|
+
current_conditions.push first.condition.invert(symtab)
|
|
26
|
+
values << [first.false_expression, current_conditions.clone]
|
|
27
|
+
current_conditions.pop
|
|
28
|
+
else
|
|
29
|
+
values << [self, current_conditions.clone]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class IfAst < AstNode
|
|
35
|
+
def pass_find_return_values(values, current_conditions, symtab)
|
|
36
|
+
current_conditions.push if_cond
|
|
37
|
+
if_body.elements.each do |e|
|
|
38
|
+
e.e.pass_find_return_values(values, current_conditions, symtab)
|
|
39
|
+
end
|
|
40
|
+
current_conditions.pop
|
|
41
|
+
|
|
42
|
+
unless elseifs.empty?
|
|
43
|
+
elseifs.elements.each do |eif|
|
|
44
|
+
current_conditions.push eif.expression
|
|
45
|
+
|
|
46
|
+
eif.body.elements.each do |e|
|
|
47
|
+
e.e.pass_find_return_values(values, current_conditions, symtab)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
current_conditions.pop
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
unless final_else.empty?
|
|
55
|
+
current_conditions.push if_cond.invert(symtab)
|
|
56
|
+
|
|
57
|
+
final_else.body.elements.each do |e|
|
|
58
|
+
e.e.pass_find_return_values(values, current_conditions, symtab)
|
|
59
|
+
end
|
|
60
|
+
current_conditions.pop
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class FunctionBodyAst < AstNode
|
|
66
|
+
# @return [Array<Ast, Array<Ast>>] List of possible return values, along with the condition it occurs under
|
|
67
|
+
def pass_find_return_values(symtab)
|
|
68
|
+
values = []
|
|
69
|
+
current_conditions = []
|
|
70
|
+
statements.each do |s|
|
|
71
|
+
s.pass_find_return_values(values, current_conditions, symtab)
|
|
72
|
+
end
|
|
73
|
+
values
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
3
|
+
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
module Idl
|
|
7
|
+
class ComplexRegDetermination < RuntimeError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class AstNode
|
|
11
|
+
def find_src_registers(symtab)
|
|
12
|
+
# if is_a?(Executable)
|
|
13
|
+
# value_result = value_try do
|
|
14
|
+
# execute(symtab)
|
|
15
|
+
# end
|
|
16
|
+
# value_else(value_result) do
|
|
17
|
+
# execute_unknown(symtab)
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
add_symbol(symtab) if is_a?(Declaration)
|
|
21
|
+
|
|
22
|
+
srcs = []
|
|
23
|
+
@children.each do |child|
|
|
24
|
+
srcs.concat(child.find_src_registers(symtab))
|
|
25
|
+
end
|
|
26
|
+
srcs.uniq
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_dst_registers(symtab)
|
|
30
|
+
# if is_a?(Executable)
|
|
31
|
+
# value_result = value_try do
|
|
32
|
+
# execute(symtab)
|
|
33
|
+
# end
|
|
34
|
+
# value_else(value_result) do
|
|
35
|
+
# execute_unknown(symtab)
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
add_symbol(symtab) if is_a?(Declaration)
|
|
39
|
+
|
|
40
|
+
srcs = []
|
|
41
|
+
@children.each do |child|
|
|
42
|
+
srcs.concat(child.find_dst_registers(symtab))
|
|
43
|
+
end
|
|
44
|
+
srcs.uniq
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class ForLoopAst
|
|
49
|
+
# we don't unroll, but we don't add the index variable to the symtab, either
|
|
50
|
+
# that will cause any register accesses dependent on the index variable to raise Complex
|
|
51
|
+
def find_src_registers(symtab)
|
|
52
|
+
srcs = init.find_src_registers(symtab)
|
|
53
|
+
# don't add init to the symtab, since we don't want to use it...
|
|
54
|
+
srcs += condition.find_src_registers(symtab)
|
|
55
|
+
|
|
56
|
+
stmts.each do |stmt|
|
|
57
|
+
srcs += stmt.find_src_registers(symtab)
|
|
58
|
+
end
|
|
59
|
+
srcs += update.find_src_registers(symtab)
|
|
60
|
+
|
|
61
|
+
srcs
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# we don't unroll, but we don't add the index variable to the symtab, either
|
|
65
|
+
# that will cause any register accesses dependent on the index variable to raise Complex
|
|
66
|
+
def find_dst_registers(symtab)
|
|
67
|
+
dsts = init.find_dst_registers(symtab)
|
|
68
|
+
# don't add init to the symtab, since we don't want to use it...
|
|
69
|
+
dsts += condition.find_dst_registers(symtab)
|
|
70
|
+
|
|
71
|
+
stmts.each do |stmt|
|
|
72
|
+
dsts += stmt.find_dst_registers(symtab)
|
|
73
|
+
end
|
|
74
|
+
dsts += update.find_dst_registers(symtab)
|
|
75
|
+
|
|
76
|
+
dsts
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class AryElementAccessAst
|
|
81
|
+
def find_src_registers(symtab)
|
|
82
|
+
value_result = value_try do
|
|
83
|
+
if var.text_value == "X"
|
|
84
|
+
return [index.value(symtab)]
|
|
85
|
+
else
|
|
86
|
+
return []
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
value_else(value_result) do
|
|
90
|
+
if var.text_value == "X"
|
|
91
|
+
if index.type(symtab).const?
|
|
92
|
+
return [index.gen_cpp(symtab, 0)]
|
|
93
|
+
else
|
|
94
|
+
raise ComplexRegDetermination
|
|
95
|
+
end
|
|
96
|
+
else
|
|
97
|
+
return []
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class AryElementAssignmentAst
|
|
104
|
+
def find_dst_registers(symtab)
|
|
105
|
+
value_result = value_try do
|
|
106
|
+
if lhs.text_value == "X"
|
|
107
|
+
return [idx.value(symtab)]
|
|
108
|
+
else
|
|
109
|
+
return []
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
value_else(value_result) do
|
|
113
|
+
if lhs.text_value == "X"
|
|
114
|
+
if idx.type(symtab).const?
|
|
115
|
+
return [idx.gen_cpp(symtab, 0)]
|
|
116
|
+
else
|
|
117
|
+
raise ComplexRegDetermination
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
return []
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|