Skip to content

Commit bf64c20

Browse files
Ellipse0934maleadt
authored andcommitted
Implement PTX syntax highlighting in Julia.
1 parent 09f8b5a commit bf64c20

File tree

2 files changed

+94
-92
lines changed

2 files changed

+94
-92
lines changed

res/pygments/ptx.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/reflection.jl

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,107 @@ const Cthulhu = Base.PkgId(UUID("f68482b8-f384-11e8-15f7-abe071a5a75f"), "Cthulh
88
# syntax highlighting
99
#
1010

11-
const _pygmentize = Ref{Union{String,Nothing}}()
12-
function pygmentize()
13-
if !isassigned(_pygmentize)
14-
_pygmentize[] = Sys.which("pygmentize")
15-
end
16-
return _pygmentize[]
17-
end
11+
# https://github.com/JuliaLang/julia/blob/dacd16f068fb27719b31effbe8929952ee2d5b32/stdlib/InteractiveUtils/src/codeview.jl
12+
const hlscheme = Dict{Symbol, Tuple{Bool, Union{Symbol, Int}}}(
13+
:default => (false, :normal), # e.g. comma, equal sign, unknown token
14+
:comment => (false, :light_black),
15+
:label => (false, :light_red),
16+
:instruction => ( true, :light_cyan),
17+
:type => (false, :cyan),
18+
:number => (false, :yellow),
19+
:bracket => (false, :yellow),
20+
:variable => (false, :normal), # e.g. variable, register
21+
:keyword => (false, :light_magenta),
22+
:funcname => (false, :light_yellow),
23+
)
1824

1925
function highlight(io::IO, code, lexer)
20-
highlighter = pygmentize()
21-
have_color = get(io, :color, false)
22-
if highlighter === nothing || !have_color
26+
if !haskey(io, :color)
2327
print(io, code)
28+
elseif lexer == "llvm"
29+
InteractiveUtils.print_llvm(io, code)
30+
elseif lexer == "ptx"
31+
highlight_ptx(io, code)
2432
else
25-
custom_lexer = joinpath(dirname(@__DIR__), "res", "pygments", "$lexer.py")
26-
if isfile(custom_lexer)
27-
lexer = `$custom_lexer -x`
28-
end
29-
30-
pipe = open(`$highlighter -f terminal -P bg=dark -l $lexer`, "r+")
31-
print(pipe, code)
32-
close(pipe.in)
33-
print(io, read(pipe, String))
33+
print(io, code)
3434
end
35-
return
3635
end
3736

37+
const ptx_instructions = [
38+
"abs", "cvt", "min", "shfl", "vadd", "activemask", "cvta", "mma", "shl", "vadd2",
39+
"add", "discard", "mov", "shr", "vadd4", "addc", "div", "mul", "sin", "vavrg2",
40+
"alloca", "dp2a", "mul24", "slct", "vavrg4", "and", "dp4a", "nanosleep", "sqrt",
41+
"vmad", "applypriority", "ex2", "neg", "st", "vmax", "atom", "exit", "not",
42+
"stackrestore", "vmax2", "bar", "fence", "or", "stacksave", "vmax4", "barrier",
43+
"fma", "pmevent", "sub", "vmin", "bfe", "fns", "popc", "subc", "vmin2", "bfi",
44+
"isspacep", "prefetch", "suld", "vmin4", "bfind", "istypep", "prefetchu", "suq",
45+
"vote", "bmsk", "ld", "prmt", "sured", "vset", "bra", "ldmatrix", "rcp", "sust",
46+
"vset2", "brev", "ldu", "red", "szext", "vset4", "brkpt", "lg2", "redux", "tanh",
47+
"vshl", "brx", "lop3", "rem", "testp", "vshr", "call", "mad", "ret", "tex", "vsub",
48+
"clz", "mad24", "rsqrt", "tld4", "vsub2", "cnot", "madc", "sad", "trap", "vsub4",
49+
"copysign", "match", "selp", "txq", "wmma", "cos", "max", "set", "vabsdiff", "xor",
50+
"cp", "mbarrier", "setp", "vabsdiff2", "createpolicy", "membar", "shf", "vabsdiff4"]
51+
52+
# simple regex-based highlighter
53+
# https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
54+
function highlight_ptx(io::IO, code)
55+
function get_token(s)
56+
# TODO: doesn't handle `ret;`, `{1`, etc; not properly tokenizing symbols
57+
m = match(r"(\s*)([^\s]+)(.*)", s)
58+
m !== nothing && (return m.captures[1:3])
59+
return nothing, nothing, nothing
60+
end
61+
print_tok(token, type) = Base.printstyled(io,
62+
token,
63+
bold = hlscheme[type][1],
64+
color = hlscheme[type][2])
65+
buf = IOBuffer(code)
66+
while !eof(buf)
67+
line = readline(buf)
68+
indent, tok, line = get_token(line)
69+
istok(regex) = match(regex, tok) !== nothing
70+
isinstr() = first(split(tok, '.')) in ptx_instructions
71+
while (tok !== nothing)
72+
print(io, indent)
73+
74+
# comments
75+
if istok(r"^\/\/")
76+
print_tok(tok, :comment)
77+
print_tok(line, :comment)
78+
break
79+
# labels
80+
elseif istok(r"^[\w]+:")
81+
print_tok(tok, :label)
82+
# instructions
83+
elseif isinstr()
84+
print_tok(tok, :instruction)
85+
# directives
86+
elseif istok(r"^\.[\w]+")
87+
print_tok(tok, :type)
88+
# guard predicates
89+
elseif istok(r"^@!?%p.+")
90+
print_tok(tok, :keyword)
91+
# registers
92+
elseif istok(r"^%[\w]+")
93+
print_tok(tok, :variable)
94+
# constants
95+
elseif istok(r"^0[xX][A-F]+U?") || # hexadecimal
96+
istok(r"^0[0-8]+U?") || # octal
97+
istok(r"^0[bB][01]+U?") || # binary
98+
istok(r"^[0-9]+U?") || # decimal
99+
istok(r"^0[fF]{hexdigit}{8}") || # single-precision floating point
100+
istok(r"^0[dD]{hexdigit}{16}") # double-precision floating point
101+
print_tok(tok, :number)
102+
# TODO: function names
103+
# TODO: labels as RHS
104+
else
105+
print_tok(tok, :default)
106+
end
107+
indent, tok, line = get_token(line)
108+
end
109+
print(io, '\n')
110+
end
111+
end
38112

39113
#
40114
# code_* replacements

0 commit comments

Comments
 (0)