Skip to content

Commit d7823fa

Browse files
committed
Use plain vectors for storing LLVM kinds and opcodes.
1 parent 6a4e935 commit d7823fa

File tree

8 files changed

+66
-50
lines changed

8 files changed

+66
-50
lines changed

src/core/basicblock.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export BasicBlock, unsafe_delete!,
55
@checked struct BasicBlock <: Value
66
ref::API.LLVMValueRef
77
end
8-
value_kinds[API.LLVMBasicBlockValueKind] = BasicBlock
8+
register(BasicBlock, API.LLVMBasicBlockValueKind)
99

1010
BasicBlock(ref::API.LLVMBasicBlockRef) = BasicBlock(API.LLVMBasicBlockAsValue(ref))
1111
Base.unsafe_convert(::Type{API.LLVMBasicBlockRef}, bb::BasicBlock) = API.LLVMValueAsBasicBlock(bb)

src/core/function.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export unsafe_delete!,
55
entry
66

77
# forward declaration of Function in src/core/basicblock.jl
8-
value_kinds[API.LLVMFunctionValueKind] = Function
8+
register(Function, API.LLVMFunctionValueKind)
99

1010
Function(mod::Module, name::String, ft::FunctionType) =
1111
Function(API.LLVMAddFunction(mod, name, ft))
@@ -81,7 +81,7 @@ export Argument, parameters
8181
@checked struct Argument <: Value
8282
ref::API.LLVMValueRef
8383
end
84-
value_kinds[API.LLVMArgumentValueKind] = Argument
84+
register(Argument, API.LLVMArgumentValueKind)
8585

8686
struct FunctionParameterSet <: AbstractVector{Argument}
8787
f::Function

src/core/instructions.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ export Instruction, unsafe_delete!,
44
predicate_int, predicate_real
55

66
# forward definition of Instruction in src/core/value/constant.jl
7-
value_kinds[API.LLVMInstructionValueKind] = Instruction
7+
register(Instruction, API.LLVMInstructionValueKind)
88

9-
const instruction_opcodes = Dict{API.LLVMOpcode, Type{<:Instruction}}()
9+
const instruction_opcodes = Vector{Type}(fill(Nothing, typemax(API.LLVMOpcode)+1))
1010
function identify(::Type{Instruction}, ref::API.LLVMValueRef)
1111
opcode = API.LLVMGetInstructionOpcode(ref)
12-
haskey(instruction_opcodes, opcode) || error("Unknown instruction opcode $opcode")
13-
return instruction_opcodes[opcode]
12+
typ = @inbounds instruction_opcodes[opcode+1]
13+
typ === Nothing && error("Unknown type opcode $opcode")
14+
return typ
15+
end
16+
function register(T::Type{<:Instruction}, opcode::API.LLVMOpcode)
17+
instruction_opcodes[opcode+1] = T
1418
end
1519

1620
function refcheck(::Type{T}, ref::API.LLVMValueRef) where T<:Instruction
@@ -120,7 +124,7 @@ for op in opcodes
120124
@checked struct $typename <: Instruction
121125
ref::API.LLVMValueRef
122126
end
123-
instruction_opcodes[API.$enum] = $typename
127+
register($typename, API.$enum)
124128
end
125129
end
126130

src/core/metadata.jl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ abstract type Metadata end
55

66
Base.unsafe_convert(::Type{API.LLVMMetadataRef}, md::Metadata) = md.ref
77

8-
const metadata_kinds = Dict{API.LLVMMetadataKind, Type{<:Metadata}}()
8+
const metadata_kinds = Vector{Type}(fill(Nothing, typemax(API.LLVMMetadataKind)+1))
99
function identify(::Type{Metadata}, ref::API.LLVMMetadataRef)
1010
kind = API.LLVMGetMetadataKind(ref)
11-
haskey(metadata_kinds, kind) || error("Unknown metadata kind $kind")
12-
return metadata_kinds[kind]
11+
typ = @inbounds metadata_kinds[kind+1]
12+
typ === Nothing && error("Unknown metadata kind $kind")
13+
return typ
14+
end
15+
function register(T::Type{<:Metadata}, kind::API.LLVMMetadataKind)
16+
metadata_kinds[kind+1] = T
1317
end
1418

1519
function refcheck(::Type{T}, ref::API.LLVMMetadataRef) where T<:Metadata
@@ -42,7 +46,7 @@ end
4246
@checked struct MetadataAsValue <: Value
4347
ref::API.LLVMValueRef
4448
end
45-
value_kinds[API.LLVMMetadataAsValueValueKind] = MetadataAsValue
49+
register(MetadataAsValue, API.LLVMMetadataAsValueValueKind)
4650

4751
Value(md::Metadata; ctx::Context) = MetadataAsValue(API.LLVMMetadataAsValue(ctx, md))
4852

@@ -57,12 +61,12 @@ abstract type ValueAsMetadata <: Metadata end
5761
@checked struct ConstantAsMetadata <: ValueAsMetadata
5862
ref::API.LLVMMetadataRef
5963
end
60-
metadata_kinds[API.LLVMConstantAsMetadataMetadataKind] = ConstantAsMetadata
64+
register(ConstantAsMetadata, API.LLVMConstantAsMetadataMetadataKind)
6165

6266
@checked struct LocalAsMetadata <: ValueAsMetadata
6367
ref::API.LLVMMetadataRef
6468
end
65-
metadata_kinds[API.LLVMLocalAsMetadataMetadataKind] = LocalAsMetadata
69+
register(LocalAsMetadata, API.LLVMLocalAsMetadataMetadataKind)
6670

6771
# NOTE: this can be used to both pack e.g. constants as metadata, and to extract the
6872
# metadata from an MetadataAsValue, so we don't type-assert narrowly here
@@ -78,7 +82,7 @@ export MDString
7882
@checked struct MDString <: Metadata
7983
ref::API.LLVMMetadataRef
8084
end
81-
metadata_kinds[API.LLVMMDStringMetadataKind] = MDString
85+
register(MDString, API.LLVMMDStringMetadataKind)
8286

8387
MDString(val::String; ctx::Context) =
8488
MDString(API.LLVMMDStringInContext2(ctx, val, length(val)))
@@ -111,7 +115,7 @@ export MDTuple
111115
@checked struct MDTuple <: MDNode
112116
ref::API.LLVMMetadataRef
113117
end
114-
metadata_kinds[API.LLVMMDTupleMetadataKind] = MDTuple
118+
register(MDTuple, API.LLVMMDTupleMetadataKind)
115119

116120
# MDTuples are commonly referred to as MDNodes, so keep that name
117121
MDNode(mds::Vector{<:Metadata}; ctx::Context) =

src/core/type.jl

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ Base.eltype(typ::LLVMType) = Any
77

88
Base.unsafe_convert(::Type{API.LLVMTypeRef}, typ::LLVMType) = typ.ref
99

10-
const type_kinds = Dict{API.LLVMTypeKind, Type{<:LLVMType}}()
10+
const type_kinds = Vector{Type}(fill(Nothing, typemax(API.LLVMTypeKind)+1))
1111
function identify(::Type{LLVMType}, ref::API.LLVMTypeRef)
1212
kind = API.LLVMGetTypeKind(ref)
13-
haskey(type_kinds, kind) || error("Unknown type kind $kind")
14-
return type_kinds[kind]
13+
typ = @inbounds type_kinds[kind+1]
14+
typ === Nothing && error("Unknown type kind $kind")
15+
return typ
16+
end
17+
function register(T::Type{<:LLVMType}, kind::API.LLVMTypeKind)
18+
type_kinds[kind+1] = T
1519
end
1620

1721
function refcheck(::Type{T}, ref::API.LLVMTypeRef) where T<:LLVMType
@@ -50,7 +54,7 @@ export width
5054
@checked struct IntegerType <: LLVMType
5155
ref::API.LLVMTypeRef
5256
end
53-
type_kinds[API.LLVMIntegerTypeKind] = IntegerType
57+
register(IntegerType, API.LLVMIntegerTypeKind)
5458

5559
for T in [:Int1, :Int8, :Int16, :Int32, :Int64, :Int128]
5660
jl_fname = Symbol(T, :Type)
@@ -84,7 +88,7 @@ for T in [:Half, :Float, :Double]
8488
@checked struct $api_typename <: FloatingPointType
8589
ref::API.LLVMTypeRef
8690
end
87-
type_kinds[API.$enumkind] = $api_typename
91+
register($api_typename, API.$enumkind)
8892

8993
$jl_fname(ctx::Context) =
9094
$api_typename(API.$(Symbol(api_fname, :InContext))(ctx))
@@ -99,7 +103,7 @@ export isvararg, return_type, parameters
99103
@checked struct FunctionType <: LLVMType
100104
ref::API.LLVMTypeRef
101105
end
102-
type_kinds[API.LLVMFunctionTypeKind] = FunctionType
106+
register(FunctionType, API.LLVMFunctionTypeKind)
103107

104108
FunctionType(rettyp::LLVMType, params::Vector{<:LLVMType}=LLVMType[];
105109
vararg::Core.Bool=false) =
@@ -138,7 +142,7 @@ Base.eltype(typ::SequentialType) = LLVMType(API.LLVMGetElementType(typ))
138142
@checked struct PointerType <: SequentialType
139143
ref::API.LLVMTypeRef
140144
end
141-
type_kinds[API.LLVMPointerTypeKind] = PointerType
145+
register(PointerType, API.LLVMPointerTypeKind)
142146

143147
function PointerType(eltyp::LLVMType, addrspace=0)
144148
return PointerType(API.LLVMPointerType(eltyp, addrspace))
@@ -151,7 +155,7 @@ addrspace(ptrtyp::PointerType) =
151155
@checked struct ArrayType <: SequentialType
152156
ref::API.LLVMTypeRef
153157
end
154-
type_kinds[API.LLVMArrayTypeKind] = ArrayType
158+
register(ArrayType, API.LLVMArrayTypeKind)
155159

156160
function ArrayType(eltyp::LLVMType, count)
157161
return ArrayType(API.LLVMArrayType(eltyp, count))
@@ -165,7 +169,7 @@ Base.isempty(@nospecialize(T::ArrayType)) = length(T) == 0 || isempty(eltype(T))
165169
@checked struct VectorType <: SequentialType
166170
ref::API.LLVMTypeRef
167171
end
168-
type_kinds[API.LLVMVectorTypeKind] = VectorType
172+
register(VectorType, API.LLVMVectorTypeKind)
169173

170174
function VectorType(eltyp::LLVMType, count)
171175
return VectorType(API.LLVMVectorType(eltyp, count))
@@ -181,7 +185,7 @@ export name, ispacked, isopaque, elements!
181185
@checked struct StructType <: SequentialType
182186
ref::API.LLVMTypeRef
183187
end
184-
type_kinds[API.LLVMStructTypeKind] = StructType
188+
register(StructType, API.LLVMStructTypeKind)
185189

186190
function StructType(name::String; ctx::Context)
187191
return StructType(API.LLVMStructCreateNamed(ctx, name))
@@ -242,28 +246,28 @@ end
242246
@checked struct VoidType <: LLVMType
243247
ref::API.LLVMTypeRef
244248
end
245-
type_kinds[API.LLVMVoidTypeKind] = VoidType
249+
register(VoidType, API.LLVMVoidTypeKind)
246250

247251
VoidType(ctx::Context) = VoidType(API.LLVMVoidTypeInContext(ctx))
248252

249253
@checked struct LabelType <: LLVMType
250254
ref::API.LLVMTypeRef
251255
end
252-
type_kinds[API.LLVMLabelTypeKind] = LabelType
256+
register(LabelType, API.LLVMLabelTypeKind)
253257

254258
LabelType(ctx::Context) = LabelType(API.LLVMLabelTypeInContext(ctx))
255259

256260
@checked struct MetadataType <: LLVMType
257261
ref::API.LLVMTypeRef
258262
end
259-
type_kinds[API.LLVMMetadataTypeKind] = MetadataType
263+
register(MetadataType, API.LLVMMetadataTypeKind)
260264

261265
MetadataType(ctx::Context) = MetadataType(API.LLVMMetadataTypeInContext(ctx))
262266

263267
@checked struct TokenType <: LLVMType
264268
ref::API.LLVMTypeRef
265269
end
266-
type_kinds[API.LLVMTokenTypeKind] = TokenType
270+
register(TokenType, API.LLVMTokenTypeKind)
267271

268272
TokenType(ctx::Context) = TokenType(API.LLVMTokenTypeInContext(ctx))
269273

src/core/value.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ abstract type Value end
88

99
Base.unsafe_convert(::Type{API.LLVMValueRef}, val::Value) = val.ref
1010

11-
const value_kinds = Dict{API.LLVMValueKind, Type{<:Value}}()
11+
const value_kinds = Vector{Type}(fill(Nothing, typemax(API.LLVMValueKind)+1))
1212
function identify(::Type{Value}, ref::API.LLVMValueRef)
1313
kind = API.LLVMGetValueKind(ref)
14-
haskey(value_kinds, kind) || error("Unknown value kind $kind")
15-
return value_kinds[kind]
14+
typ = @inbounds value_kinds[kind+1]
15+
typ === Nothing && error("Unknown value kind $kind")
16+
return typ
17+
end
18+
function register(T::Type{<:Value}, kind::API.LLVMValueKind)
19+
value_kinds[kind+1] = T
1620
end
1721

1822
function refcheck(::Type{T}, ref::API.LLVMValueRef) where T<:Value

src/core/value/constant.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ abstract type Instruction <: User end
1919
@checked struct PointerNull <: Constant
2020
ref::API.LLVMValueRef
2121
end
22-
value_kinds[API.LLVMConstantPointerNullValueKind] = PointerNull
22+
register(PointerNull, API.LLVMConstantPointerNullValueKind)
2323

2424
PointerNull(typ::PointerType) = PointerNull(API.LLVMConstPointerNull(typ))
2525

2626

2727
@checked struct UndefValue <: Constant
2828
ref::API.LLVMValueRef
2929
end
30-
value_kinds[API.LLVMUndefValueValueKind] = UndefValue
30+
register(UndefValue, API.LLVMUndefValueValueKind)
3131

3232
UndefValue(typ::LLVMType) = UndefValue(API.LLVMGetUndef(typ))
3333

@@ -39,7 +39,7 @@ export ConstantInt, ConstantFP
3939
@checked struct ConstantInt <: Constant
4040
ref::API.LLVMValueRef
4141
end
42-
value_kinds[API.LLVMConstantIntValueKind] = ConstantInt
42+
register(ConstantInt, API.LLVMConstantIntValueKind)
4343

4444
# NOTE: fixed set for dispatch, also because we can't rely on sizeof(T)==width(T)
4545
const WideInteger = Union{Int64, UInt64}
@@ -83,7 +83,7 @@ Base.convert(::Type{Core.Bool}, val::ConstantInt) = convert(Int, val) != 0
8383
@checked struct ConstantFP <: Constant
8484
ref::API.LLVMValueRef
8585
end
86-
value_kinds[API.LLVMConstantFPValueKind] = ConstantFP
86+
register(ConstantFP, API.LLVMConstantFPValueKind)
8787

8888
ConstantFP(typ::FloatingPointType, val::Real) =
8989
ConstantFP(API.LLVMConstReal(typ, Cdouble(val)))
@@ -106,7 +106,7 @@ export ConstantAggregateZero
106106
@checked struct ConstantAggregateZero <: Constant
107107
ref::API.LLVMValueRef
108108
end
109-
value_kinds[API.LLVMConstantAggregateZeroValueKind] = ConstantAggregateZero
109+
register(ConstantAggregateZero, API.LLVMConstantAggregateZeroValueKind)
110110

111111
# array interface
112112
# FIXME: can we reuse the ::ConstantArray functionality with ConstantAggregateZero values?
@@ -127,8 +127,8 @@ abstract type ConstantAggregate <: Constant end
127127
@checked struct ConstantArray <: ConstantAggregate
128128
ref::API.LLVMValueRef
129129
end
130-
value_kinds[API.LLVMConstantArrayValueKind] = ConstantArray
131-
value_kinds[API.LLVMConstantDataArrayValueKind] = ConstantArray
130+
register(ConstantArray, API.LLVMConstantArrayValueKind)
131+
register(ConstantArray, API.LLVMConstantDataArrayValueKind)
132132

133133
ConstantArrayOrAggregateZero(value) = Value(value)::Union{ConstantArray,ConstantAggregateZero}
134134

@@ -205,7 +205,7 @@ end
205205
@checked struct ConstantStruct <: ConstantAggregate
206206
ref::API.LLVMValueRef
207207
end
208-
value_kinds[API.LLVMConstantStructValueKind] = ConstantStruct
208+
register(ConstantStruct, API.LLVMConstantStructValueKind)
209209

210210
ConstantStructOrAggregateZero(value) = Value(value)::Union{ConstantStruct,ConstantAggregateZero}
211211

@@ -256,7 +256,7 @@ end
256256
@checked struct ConstantVector <: ConstantAggregate
257257
ref::API.LLVMValueRef
258258
end
259-
value_kinds[API.LLVMConstantVectorValueKind] = ConstantVector
259+
register(ConstantVector, API.LLVMConstantVectorValueKind)
260260

261261

262262
## constant expressions
@@ -266,15 +266,15 @@ export ConstantExpr, ConstantAggregate, ConstantArray, ConstantStruct, ConstantV
266266
@checked struct ConstantExpr <: Constant
267267
ref::API.LLVMValueRef
268268
end
269-
value_kinds[API.LLVMConstantExprValueKind] = ConstantExpr
269+
register(ConstantExpr, API.LLVMConstantExprValueKind)
270270

271271

272272
## inline assembly
273273

274274
@checked struct InlineAsm <: Constant
275275
ref::API.LLVMValueRef
276276
end
277-
value_kinds[API.LLVMInlineAsmValueKind] = InlineAsm
277+
register(InlineAsm, API.LLVMInlineAsmValueKind)
278278

279279
InlineAsm(typ::FunctionType, asm::String, constraints::String,
280280
side_effects::Core.Bool, align_stack::Core.Bool=false) =
@@ -352,7 +352,7 @@ export GlobalVariable, unsafe_delete!,
352352
@checked struct GlobalVariable <: GlobalObject
353353
ref::API.LLVMValueRef
354354
end
355-
value_kinds[API.LLVMGlobalVariableValueKind] = GlobalVariable
355+
register(GlobalVariable, API.LLVMGlobalVariableValueKind)
356356

357357
GlobalVariable(mod::Module, typ::LLVMType, name::String) =
358358
GlobalVariable(API.LLVMAddGlobal(mod, typ, name))

src/debuginfo.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export DILocation
55
@checked struct DILocation <: MDNode
66
ref::API.LLVMMetadataRef
77
end
8-
metadata_kinds[API.LLVMDILocationMetadataKind] = DILocation
8+
register(DILocation, API.LLVMDILocationMetadataKind)
99

1010
line(location::DILocation) = Int(API.LLVMDILocationGetLine(location))
1111
column(location::DILocation) = Int(API.LLVMDILocationGetColumn(location))
@@ -41,7 +41,7 @@ for var in (:Local, :Global)
4141
@checked struct $var_name <: DIVariable
4242
ref::API.LLVMMetadataRef
4343
end
44-
metadata_kinds[API.$var_kind] = $var_name
44+
register($var_name, API.$var_kind)
4545
end
4646
end
4747

@@ -77,7 +77,7 @@ export DIFile
7777
@checked struct DIFile <: DIScope
7878
ref::API.LLVMMetadataRef
7979
end
80-
metadata_kinds[API.LLVMDIFileMetadataKind] = DIFile
80+
register(DIFile, API.LLVMDIFileMetadataKind)
8181

8282
function directory(file::DIFile)
8383
len = Ref{Cuint}()
@@ -111,7 +111,7 @@ for typ in (:Basic, :Derived, :Composite, :Subroutine)
111111
@checked struct $typ_name <: DIType
112112
ref::API.LLVMMetadataRef
113113
end
114-
metadata_kinds[API.$typ_kind] = $typ_name
114+
register($typ_name, API.$typ_kind)
115115
end
116116
end
117117

@@ -134,7 +134,7 @@ export DISubProgram
134134
@checked struct DISubProgram <: DIScope
135135
ref::API.LLVMMetadataRef
136136
end
137-
metadata_kinds[API.LLVMDISubprogramMetadataKind] = DISubProgram
137+
register(DISubProgram, API.LLVMDISubprogramMetadataKind)
138138

139139
line(subprogram::DISubProgram) = Int(API.LLVMDISubprogramGetLine(subprogram))
140140

0 commit comments

Comments
 (0)