Skip to content

Commit 1de83c1

Browse files
authored
Fix some edge cases for mangling (#672)
1 parent a0fd55d commit 1de83c1

File tree

2 files changed

+75
-34
lines changed

2 files changed

+75
-34
lines changed

src/mangling.jl

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,33 @@ safe_name(x) = safe_name(repr(x))
2929
# we generate function names that look like C++ functions, because many tools, like NVIDIA's
3030
# profilers, support them (grouping different instantiations of the same kernel together).
3131

32-
function mangle_param(t, substitutions=Any[])
32+
function mangle_param(t, substitutions = Any[], top = false)
3333
t == Nothing && return "v"
3434

3535
function find_substitution(x)
3636
sub = findfirst(isequal(x), substitutions)
37-
if sub === nothing
37+
res = if sub === nothing
3838
nothing
3939
elseif sub == 1
4040
"S_"
4141
else
4242
seq_id = uppercase(string(sub-2; base=36))
4343
"S$(seq_id)_"
4444
end
45+
return res
46+
end
47+
48+
# check if we already know this type
49+
str = find_substitution(t)
50+
if str !== nothing
51+
return str
4552
end
4653

4754
if isa(t, DataType) && t <: Ptr
4855
tn = mangle_param(eltype(t), substitutions)
56+
push!(substitutions, t)
4957
"P$tn"
5058
elseif isa(t, DataType)
51-
# check if we already know this type
52-
str = find_substitution(t)
53-
if str !== nothing
54-
return str
55-
end
56-
5759
# check if we already know this base type
5860
str = find_substitution(t.name.wrapper)
5961
if str === nothing
@@ -62,47 +64,66 @@ function mangle_param(t, substitutions=Any[])
6264
push!(substitutions, t.name.wrapper)
6365
end
6466

65-
# encode typevars as template parameters
66-
if !isempty(t.parameters)
67-
str *= "I"
68-
for t in t.parameters
69-
str *= mangle_param(t, substitutions)
67+
if t.name.wrapper == t && !isa(t.name.wrapper, UnionAll)
68+
# a type with no typevars
69+
str
70+
else
71+
# encode typevars as template parameters
72+
if isempty(t.parameters)
73+
w_types = t.name.wrapper.types
74+
if !isempty(w_types) && !isempty(w_types[end] isa Core.TypeofVararg)
75+
# If the type accepts a variable amount of parameters,
76+
# e.g. `Tuple{}`, then we mark it as empty: "Tuple<>"
77+
str *= "IJEE"
78+
end
79+
else
80+
str *= "I"
81+
for tp in t.parameters
82+
str *= mangle_param(tp, substitutions)
83+
end
84+
str *= "E"
7085
end
71-
str *= "E"
72-
7386
push!(substitutions, t)
87+
str
7488
end
75-
76-
str
7789
elseif isa(t, Union)
78-
# check if we already know this union type
79-
str = find_substitution(t)
80-
if str !== nothing
81-
return str
82-
end
83-
8490
# check if we already know the Union name
8591
str = find_substitution(Union)
8692
if str === nothing
8793
tn = "Union"
8894
str = "$(length(tn))$tn"
89-
push!(substitutions, tn)
95+
push!(substitutions, Union)
9096
end
9197

9298
# encode union types as template parameters
93-
if !isempty(Base.uniontypes(t))
94-
str *= "I"
95-
for t in Base.uniontypes(t)
96-
str *= mangle_param(t, substitutions)
97-
end
98-
str *= "E"
99-
100-
push!(substitutions, t)
99+
str *= "I"
100+
for tp in Base.uniontypes(t) # cannot be empty as `Union{}` is not a `Union`
101+
str *= mangle_param(tp, substitutions)
101102
end
103+
str *= "E"
102104

105+
push!(substitutions, t)
103106
str
104107
elseif isa(t, UnionAll)
105-
mangle_param(t.body, substitutions)
108+
mangle_param(Base.unwrap_unionall(t), substitutions)
109+
elseif isa(t, Core.TypeofVararg)
110+
T = isdefined(t, :T) ? t.T : Any
111+
if isdefined(t, :N)
112+
# For NTuple, repeat the type as needed
113+
str = ""
114+
for _ in 1:t.N
115+
str *= mangle_param(T, substitutions)
116+
end
117+
str
118+
elseif top
119+
# Variadic arguments only make sense for function arguments
120+
mangle_param(T, substitutions) * "z" # T...
121+
else
122+
# Treat variadic arguments for a type as no arguments
123+
""
124+
end
125+
elseif isa(t, Char)
126+
mangle_param(UInt32(t), substitutions)
106127
elseif isa(t, Union{Bool, Cchar, Cuchar, Cshort, Cushort, Cint, Cuint, Clong, Culong, Clonglong, Culonglong, Int128, UInt128})
107128
ts = t isa Bool ? 'b' : # bool
108129
t isa Cchar ? 'a' : # signed char
@@ -153,7 +174,7 @@ function mangle_sig(sig)
153174
# mangle each parameter
154175
substitutions = []
155176
for t in tt
156-
str *= mangle_param(t, substitutions)
177+
str *= mangle_param(t, substitutions, true)
157178
end
158179

159180
return str

test/utils.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,39 @@ end
2929
@test mangle(identity, Val{Cshort(1)}) == "identity(Val<(short)1>)"
3030
@test mangle(identity, Val{1.0}) == "identity(Val<0x1p+0>)"
3131
@test mangle(identity, Val{1f0}) == "identity(Val<0x1p+0f>)"
32+
@test mangle(identity, Val{'a'}) == "identity(Val<97u>)"
33+
@test mangle(identity, Val{''}) == "identity(Val<8709u>)"
3234

3335
# unions
3436
@test mangle(identity, Union{Int32, Int64}) == "identity(Union<Int32, Int64>)"
37+
@test mangle(identity, Union, Int, Union{Int64, Int32}) == "identity(Union, Int64, Union<Int32, Int64>)"
3538

3639
# union alls
3740
@test mangle(identity, Array) == "identity(Array<T, N>)"
41+
@test mangle(identity, Tuple) == "identity(Tuple)"
42+
@test mangle(identity, Vector) == "identity(Array<T, 1>)"
43+
@test mangle(identity, NTuple{2, I} where {I <: Integer}) == "identity(Tuple<I__Integer, I__Integer>)"
44+
45+
# Vararg
46+
@test mangle(identity, Vararg{Int}) == "identity(Int64, ...)"
47+
@test mangle(identity, Vararg{Int, 2}) == "identity(Int64, Int64)"
48+
@test mangle(identity, Tuple{1, 2}, Tuple{}, Tuple) == "identity(Tuple<1, 2>, Tuple<>, Tuple)"
49+
@test mangle(identity, NTuple{2, Int}) == "identity(Tuple<Int64, Int64>)"
50+
@test mangle(identity, Tuple{Vararg{Int}}) == "identity(Tuple<>)"
3851

3952
# many substitutions
4053
@test mangle(identity, Val{1}, Val{2}, Val{3}, Val{4}, Val{5}, Val{6}, Val{7}, Val{8},
4154
Val{9}, Val{10}, Val{11}, Val{12}, Val{13}, Val{14}, Val{15},
4255
Val{16}, Val{16}) ==
4356
"identity(Val<1>, Val<2>, Val<3>, Val<4>, Val<5>, Val<6>, Val<7>, Val<8>, Val<9>, Val<10>, Val<11>, Val<12>, Val<13>, Val<14>, Val<15>, Val<16>, Val<16>)"
4457

58+
# intertwined substitutions
59+
@test mangle(
60+
identity, Val{1}, Ptr{Tuple{Ptr{Int}}}, Ptr{Int}, Val{1}, Val{2},
61+
Tuple{Ptr{Int}}, Tuple{Int8}, Int64, Int8
62+
) ==
63+
"identity(Val<1>, Tuple<Int64*>*, Int64*, Val<1>, Val<2>, Tuple<Int64*>, Tuple<Int8>, Int64, Int8)"
64+
4565
# problematic examples
4666
@test mangle(identity, String, Matrix{Float32}, Broadcast.Broadcasted{Broadcast.ArrayStyle{Matrix{Float32}}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(Base.literal_pow), Tuple{Base.RefValue{typeof(sin)}, Broadcast.Extruded{Matrix{Float32}, Tuple{Bool, Bool}, Tuple{Int64, Int64}}}}) == "identity(String, Array<Float32, 2>, Broadcasted<ArrayStyle<Array<Float32, 2>>, Tuple<OneTo<Int64>, OneTo<Int64>>, literal_pow, Tuple<RefValue<sin>, Extruded<Array<Float32, 2>, Tuple<Bool, Bool>, Tuple<Int64, Int64>>>>)"
4767
end

0 commit comments

Comments
 (0)