summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2019-03-11 09:20:12 +0100
committerAdam Stankiewicz <sheerun@sher.pl>2019-03-11 09:20:36 +0100
commit420a65e9b0ab88095cd88c49167ab441a4dd1f3e (patch)
treee06444dd62853d76c3efdeb05b8a44e2bf98dc37
parent2254b83675e3356f42cc011133da67c26512022f (diff)
downloadvim-polyglot-420a65e9b0ab88095cd88c49167ab441a4dd1f3e.tar.gz
vim-polyglot-420a65e9b0ab88095cd88c49167ab441a4dd1f3e.zip
Add llvm support, closes #376v3.7.0
-rw-r--r--README.md3
-rw-r--r--after/ftplugin/llvm.vim477
-rw-r--r--after/syntax/llvm.vim26
-rwxr-xr-xbuild1
-rw-r--r--ftdetect/polyglot.vim21
-rw-r--r--ftplugin/llvm.vim16
-rw-r--r--ftplugin/tablegen.vim16
-rw-r--r--indent/llvm.vim76
-rw-r--r--syntax/llvm.vim237
-rw-r--r--syntax/tablegen.vim58
10 files changed, 930 insertions, 1 deletions
diff --git a/README.md b/README.md
index c93d05a0..1231d35e 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ A collection of language packs for Vim.
> One to rule them all, one to find them, one to bring them all and in the darkness bind them.
- It **won't affect your startup time**, as scripts are loaded only on demand\*.
-- It **installs and updates 100+ times faster** than the <!--Package Count-->132<!--/Package Count--> packages it consists of.
+- It **installs and updates 100+ times faster** than the <!--Package Count-->133<!--/Package Count--> packages it consists of.
- Solid syntax and indentation support (other features skipped). Only the best language packs.
- All unnecessary files are ignored (like enormous documentation from php support).
- No support for esoteric languages, only most popular ones (modern too, like `slim`).
@@ -110,6 +110,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [lilypond](https://github.com/anowlcalledjosh/vim-lilypond) (syntax, indent, compiler, ftplugin)
- [liquid](https://github.com/tpope/vim-liquid) (syntax, indent, ftplugin)
- [livescript](https://github.com/gkz/vim-ls) (syntax, indent, compiler, ftplugin)
+- [llvm](https://github.com/rhysd/vim-llvm) (syntax, indent, ftplugin)
- [lua](https://github.com/tbastos/vim-lua) (syntax, indent)
- [mako](https://github.com/sophacles/vim-bundle-mako) (syntax, indent, ftplugin)
- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, indent)
diff --git a/after/ftplugin/llvm.vim b/after/ftplugin/llvm.vim
new file mode 100644
index 00000000..70f196c8
--- /dev/null
+++ b/after/ftplugin/llvm.vim
@@ -0,0 +1,477 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Copyright (c) 2018 rhysd
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to deal
+" in the Software without restriction, including without limitation the rights
+" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+" copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+" THE SOFTWARE.
+
+if get(g:, 'llvm_extends_official', 1) == 0
+ finish
+endif
+
+let g:llvm_ext_no_mapping = get(g:, 'llvm_ext_no_mapping', 0)
+let g:llvm_ext_lli_executable = get(g:, 'llvm_ext_lli_executable', 'lli')
+
+let s:KIND_BLOCK_PREC = 0
+let s:KIND_BLOCK_FOLLOW = 1
+let s:KIND_FUNC_BEGIN = 2
+let s:KIND_FUNC_END = 3
+
+function! s:section_delim_at(lnum) abort
+ let line = getline(a:lnum)
+ let m = matchlist(line, '^\([^:]\+\):\%( \+; preds = \(%.\+\)\)\=$')
+ if !empty(m)
+ if m[2] ==# ''
+ return [s:KIND_BLOCK_PREC, m[1]]
+ else
+ return [s:KIND_BLOCK_FOLLOW, m[1], split(m[2], ',\s*')]
+ endif
+ endif
+ if line =~# '^}$'
+ return [s:KIND_FUNC_END]
+ endif
+ if line =~# '^define\>'
+ return [s:KIND_FUNC_BEGIN]
+ endif
+ return []
+endfunction
+
+function! s:is_section_delim(line, func_delim) abort
+ let sec = s:section_delim_at(a:line)
+ if empty(sec)
+ return 0
+ endif
+ let kind = sec[0]
+ return kind == s:KIND_BLOCK_PREC || kind == s:KIND_BLOCK_FOLLOW || kind == func_delim
+endfunction
+
+function! s:next_section(stop_func_begin) abort
+ let func_delim = a:stop_func_begin ? s:KIND_FUNC_BEGIN : s:KIND_FUNC_END
+ let last = line('$') - 1
+ let line = line('.')
+ while line < last
+ let line += 1
+ if s:is_section_delim(line, func_delim)
+ call cursor(line, col('.'))
+ return
+ endif
+ endwhile
+endfunction
+
+function! s:prev_section(stop_func_begin) abort
+ let func_delim = a:stop_func_begin ? s:KIND_FUNC_BEGIN : s:KIND_FUNC_END
+ let line = line('.')
+ while line > 1
+ let line -= 1
+ if s:is_section_delim(line, func_delim)
+ call cursor(line, col('.'))
+ return
+ endif
+ endwhile
+endfunction
+
+if !g:llvm_ext_no_mapping
+ nnoremap <buffer><silent>]] :<C-u>call <SID>next_section(1)<CR>
+ nnoremap <buffer><silent>[[ :<C-u>call <SID>prev_section(1)<CR>
+ nnoremap <buffer><silent>][ :<C-u>call <SID>next_section(0)<CR>
+ nnoremap <buffer><silent>[] :<C-u>call <SID>prev_section(0)<CR>
+endif
+
+function! s:function_range_at(linum) abort
+ let line = a:linum
+ while line >= 1
+ let s = getline(line)
+ if s =~# '^define\>'
+ let start = line
+ break
+ elseif s =~# '^}$'
+ return []
+ endif
+ let line -= 1
+ endwhile
+ if line < 1
+ return []
+ endif
+
+ let line = a:linum
+ let last = line('$')
+ while line <= last
+ let s = getline(line)
+ if s =~# '^}$'
+ let end = line
+ break
+ elseif s =~# '^define\>'
+ return []
+ endif
+ let line += 1
+ endwhile
+ if line > last
+ return []
+ endif
+
+ return [start, end]
+endfunction
+
+function! s:blocks_graph_at(linum) abort
+ let func_range = s:function_range_at(a:linum)
+ if empty(func_range)
+ return {}
+ endif
+ let line = func_range[0] + 1
+ let last = func_range[1] - 1
+ let graph = {}
+ while line <= last
+ let block = s:section_delim_at(line)
+ if empty(block)
+ let line += 1
+ continue
+ endif
+ let block_name = '%' . block[1]
+ if block[0] == s:KIND_BLOCK_PREC
+ let graph[block_name] = {'line': line, 'follows': [], 'preds': []}
+ elseif block[0] == s:KIND_BLOCK_FOLLOW
+ let graph[block_name] = {'line': line, 'follows': [], 'preds': block[2]}
+ for follow in block[2]
+ call add(graph[follow].follows, block_name)
+ endfor
+ else
+ echoerr 'unreachable'
+ endif
+ let line += 1
+ endwhile
+ return graph
+endfunction
+
+function! s:find_pred_block(linum) abort
+ let sec = s:section_delim_at(a:linum)
+ if empty(sec) || sec[0] != s:KIND_BLOCK_PREC && sec[0] != s:KIND_BLOCK_FOLLOW
+ throw 'No block is starting at line ' . a:linum
+ endif
+ if sec[0] != s:KIND_BLOCK_FOLLOW
+ throw printf("Block '%s' has no pred block", sec[1])
+ endif
+ let block_name = '%' . sec[1]
+ let pred_block = sec[2][0]
+
+ let graph = s:blocks_graph_at(a:linum)
+ if empty(graph)
+ throw 'No block is found in function at line ' . a:linum
+ endif
+
+ if !has_key(graph, pred_block)
+ throw printf("Block '%s' (pred block of '%s') not found in function", pred_block, block_name)
+ endif
+ return graph[pred_block]
+endfunction
+
+function! s:move_to_pred_block() abort
+ try
+ let b = s:find_pred_block(line('.'))
+ call cursor(b.line, col('.'))
+ catch
+ echohl ErrorMsg | echom v:exception | echohl None
+ endtry
+endfunction
+
+function! s:find_following_block(linum) abort
+ let sec = s:section_delim_at(a:linum)
+ if empty(sec) || sec[0] != s:KIND_BLOCK_PREC && sec[0] != s:KIND_BLOCK_FOLLOW
+ throw 'No block is starting at line ' . a:linum
+ endif
+ let block_name = '%' . sec[1]
+
+ let graph = s:blocks_graph_at(a:linum)
+ if empty(graph)
+ throw 'No block is found in function at line ' . a:linum
+ endif
+
+ let follows = graph[block_name].follows
+ if empty(follows)
+ throw printf("Block '%s' has no following block", block_name)
+ endif
+
+ echom printf("Block '%s' has %d following blocks: %s", block_name, len(follows), join(follows, ', '))
+
+ if !has_key(graph, follows[0])
+ throw printf("Block '%s' is not defined in function at line %d", follows[0], a:linum)
+ endif
+ return graph[follows[0]]
+endfunction
+
+function! s:move_to_following_block() abort
+ try
+ let b = s:find_following_block(line('.'))
+ call cursor(b.line, col('.'))
+ catch
+ echohl ErrorMsg | echom v:exception | echohl None
+ endtry
+endfunction
+
+if !g:llvm_ext_no_mapping
+ nnoremap <buffer><silent>[b :<C-u>call <SID>move_to_pred_block()<CR>
+ nnoremap <buffer><silent>]b :<C-u>call <SID>move_to_following_block()<CR>
+endif
+
+function! s:get_func_identifiers(line) abort
+ let idx = stridx(a:line, '@')
+ if idx == -1
+ " Invalid signature
+ return []
+ endif
+
+ " e.g. define internal i32 @foo(...) { -> @foo(...) {
+ let sig = a:line[idx:]
+
+ let idx = stridx(sig, '(')
+ if idx == -1
+ " Invalid signature
+ return []
+ endif
+
+ " @foo(...) { -> @foo
+ let idents = [sig[:idx-1]]
+
+ " @foo(...) { -> ...) {
+ let params = sig[idx+1:]
+
+ let idx = strridx(sig, ')')
+ if idx == -1
+ return idents
+ endif
+
+ " ...) { -> ...
+ let params = params[:idx-1]
+
+ " Gather parameters in function signature
+ while params !=# ''
+ let m = matchlist(params, '^[^%]*\(%\%("[^"]\+"\|[[:alnum:]_.]\+\)\)\s*\(.*\)$')
+ if empty(m)
+ break
+ endif
+ let idents += [m[1]]
+ let params = m[2]
+ endwhile
+
+ return idents
+endfunction
+
+function! s:get_identifiers(line) abort
+ " Registers and type defs
+ let m = matchlist(a:line, '^\s*\(%\S\+\)\s\+=')
+ if !empty(m)
+ return [m[1]]
+ endif
+
+ " Constants
+ let m = matchlist(a:line, '^\(@\S\+\)\s\+=.\+\<constant\>')
+ if !empty(m)
+ return [m[1]]
+ endif
+
+ " Labels for basic blocks
+ let m = matchlist(a:line, '^\([^:]\+\):\%(\s\+; preds = .\+\)\=$')
+ if !empty(m)
+ return ['%' . m[1]]
+ endif
+
+ " Meta variables
+ let m = matchlist(a:line, '^\(!\S\+\)\s\+=')
+ if !empty(m)
+ return [m[1]]
+ endif
+
+ " Attributes
+ let m = matchlist(a:line, '^attributes\s\+\(#\d\+\)\s\+=')
+ if !empty(m)
+ return [m[1]]
+ endif
+
+ if a:line =~# '^\%(declare\|define\)\>'
+ return s:get_func_identifiers(a:line)
+ endif
+
+ return []
+endfunction
+
+function! s:extract_identifier(word) abort
+ if strlen(a:word) <= 1
+ return ''
+ endif
+
+ let prefix = a:word[0]
+ if prefix ==# '@' || prefix ==# '%' || prefix ==# '!'
+ if prefix ==# '!' && a:word[1] ==# '{'
+ return ''
+ endif
+
+ if a:word[1] == '"'
+ let idx = stridx(a:word, '"', 2)
+ if idx == -1
+ return ''
+ endif
+ " @"foo" or %"foo"
+ return a:word[:idx]
+ else
+ " @foo or %foo
+ return matchstr(a:word, '^[@%!][[:alnum:]_.]\+')
+ endif
+ endif
+
+ if prefix ==# '#'
+ return matchstr(a:word, '^#\d\+')
+ endif
+
+ return ''
+endfunction
+
+function! s:jump_to_identifier_at(linum, ident) abort
+ let line = getline(a:linum)
+ let column = stridx(line, a:ident) + 1
+ if column == 0
+ let column = col('.')
+ endif
+ call cursor(a:linum, column)
+endfunction
+
+function! s:browser_open_command() abort
+ if exists('g:llvm_ext_browser_open_command')
+ return g:llvm_ext_browser_open_command
+ endif
+ if exists('s:browser_opener')
+ return s:browser_opener
+ endif
+ let s:browser_opener = ''
+ if has('mac')
+ let s:browser_opener = 'open'
+ elseif has('win32') || has('win64')
+ let s:browser_opener = 'cmd /q /c start ""'
+ else
+ for cmd in ['xdg-open', 'chromium', 'google-chrome', 'firefox']
+ if executable(cmd)
+ let s:browser_opener = cmd
+ break
+ endif
+ endfor
+ endif
+ return s:browser_opener
+endfunction
+
+function! s:open_browser(url) abort
+ let cmd = s:browser_open_command()
+ if cmd ==# ''
+ throw "Failed to open a browser. I don't know how to open a browser: Please set g:llvm_ext_browser_open_command"
+ endif
+ let cmdline = cmd . ' ' . shellescape(a:url)
+ let out = system(cmdline)
+ if v:shell_error
+ throw printf("Failed to open a browser with command '%s': %s", cmdline, out)
+ endif
+endfunction
+
+function! s:goto_definition() abort
+ " Open language reference manual under the cursor in browser
+ let syn_name = synIDattr(synID(line('.'),col('.'),1),'name')
+ if syn_name ==# 'llvmStatement'
+ let word = expand('<cword>')
+ if word !=# ''
+ try
+ " Open browser assuming a word under the cursor is an instruction
+ call s:open_browser('https://llvm.org/docs/LangRef.html#' . word . '-instruction')
+ catch /^Failed to open a browser/
+ echohl ErrorMsg | echom v:exception | echohl None
+ endtry
+ endif
+ return
+ endif
+
+ " XXX: This does not support identifiers which contains spaces
+ let word = expand('<cWORD>')
+ if word ==# ''
+ echom 'No identifier found under the cursor'
+ return
+ endif
+ let ident = s:extract_identifier(word)
+ if ident ==# ''
+ echom 'No identifier found under the cursor'
+ return
+ endif
+
+ " Definition tends to be near its usages. Look back at first.
+ let line = line('.')
+ while line > 0
+ for found in s:get_identifiers(getline(line))
+ if ident ==# found
+ call s:jump_to_identifier_at(line, ident)
+ return
+ endif
+ endfor
+ let line -= 1
+ endwhile
+
+ let line = line('.') + 1
+ let last = line('$')
+ while line <= last
+ for found in s:get_identifiers(getline(line))
+ if ident ==# found
+ call s:jump_to_identifier_at(line, ident)
+ return
+ endif
+ endfor
+ let line += 1
+ endwhile
+
+ echom "No definition for '" . ident . "' found"
+endfunction
+
+if !g:llvm_ext_no_mapping
+ nnoremap <buffer><silent>K :<C-u>call <SID>goto_definition()<CR>
+endif
+
+function! s:run_lli(...) abort
+ if !has('job') || !has('channel') || !has('terminal')
+ echohl ErrorMsg
+ echomsg ':LLI requires terminal feature. Please update your Vim to 8.0+'
+ echohl None
+ return
+ endif
+
+ if !executable(g:llvm_ext_lli_executable)
+ echohl ErrorMsg
+ echomsg g:llvm_ext_lli_executable . ' is not executable. Please set g:llvm_ext_lli_executable'
+ echohl None
+ return
+ endif
+
+ if a:0 > 0
+ let bufnr = term_start([g:llvm_ext_lli_executable, a:1])
+ echo 'Run lli in termnal buffer(' . bufnr . ')'
+ return
+ endif
+
+ let tmpfile = tempname()
+ call writefile(getline(1, '$'), tmpfile)
+ let Cleanup = {ch -> filereadable(tmpfile) ? delete(tmpfile) : 0}
+ let bufnr = term_start([g:llvm_ext_lli_executable, tmpfile], {'close_cb': Cleanup, 'exit_cb': Cleanup})
+ echo 'Run lli in termnal buffer(' . bufnr . ')'
+endfunction
+
+if !exists(':LLI')
+ command! -buffer -nargs=? -bar -complete=file LLI call <SID>run_lli(<f-args>)
+endif
diff --git a/after/syntax/llvm.vim b/after/syntax/llvm.vim
new file mode 100644
index 00000000..aae8711c
--- /dev/null
+++ b/after/syntax/llvm.vim
@@ -0,0 +1,26 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Copyright (c) 2018 rhysd
+"
+" Permission is hereby granted, free of charge, to any person obtaining a copy
+" of this software and associated documentation files (the "Software"), to deal
+" in the Software without restriction, including without limitation the rights
+" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+" copies of the Software, and to permit persons to whom the Software is
+" furnished to do so, subject to the following conditions:
+"
+" The above copyright notice and this permission notice shall be included in
+" all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+" THE SOFTWARE.
+
+syn keyword llvmKeyword attributes
+syn match llvmNoName /#\d\+\>/
diff --git a/build b/build
index b928804d..e34a48bc 100755
--- a/build
+++ b/build
@@ -218,6 +218,7 @@ PACKS="
liquid:tpope/vim-liquid
lilypond:anowlcalledjosh/vim-lilypond
livescript:gkz/vim-ls
+ llvm:rhysd/vim-llvm
lua:tbastos/vim-lua
mako:sophacles/vim-bundle-mako
markdown:plasticboy/vim-markdown:_SYNTAX
diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim
index f1fc4962..37fc5552 100644
--- a/ftdetect/polyglot.vim
+++ b/ftdetect/polyglot.vim
@@ -714,6 +714,27 @@ autocmd BufNewFile,BufRead *Slakefile set filetype=ls
augroup end
endif
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'llvm') == -1
+ augroup filetypedetect
+ " llvm, from llvm-lit.vim in rhysd/vim-llvm
+au BufRead,BufNewFile lit.*cfg set filetype=python
+ augroup end
+endif
+
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'llvm') == -1
+ augroup filetypedetect
+ " llvm, from llvm.vim in rhysd/vim-llvm
+au BufRead,BufNewFile *.ll set filetype=llvm
+ augroup end
+endif
+
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'llvm') == -1
+ augroup filetypedetect
+ " llvm, from tablegen.vim in rhysd/vim-llvm
+au BufRead,BufNewFile *.td set filetype=tablegen
+ augroup end
+endif
+
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'mako') == -1
augroup filetypedetect
" mako, from mako.vim in sophacles/vim-bundle-mako
diff --git a/ftplugin/llvm.vim b/ftplugin/llvm.vim
new file mode 100644
index 00000000..0006c288
--- /dev/null
+++ b/ftplugin/llvm.vim
@@ -0,0 +1,16 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Vim filetype plugin file
+" Language: LLVM Assembly
+" Maintainer: The LLVM team, http://llvm.org/
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+setlocal softtabstop=2 shiftwidth=2
+setlocal expandtab
+setlocal comments+=:;
diff --git a/ftplugin/tablegen.vim b/ftplugin/tablegen.vim
new file mode 100644
index 00000000..94909ef5
--- /dev/null
+++ b/ftplugin/tablegen.vim
@@ -0,0 +1,16 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Vim filetype plugin file
+" Language: LLVM TableGen
+" Maintainer: The LLVM team, http://llvm.org/
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+setlocal matchpairs+=<:>
+setlocal softtabstop=2 shiftwidth=2
+setlocal expandtab
diff --git a/indent/llvm.vim b/indent/llvm.vim
new file mode 100644
index 00000000..90829c25
--- /dev/null
+++ b/indent/llvm.vim
@@ -0,0 +1,76 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Vim indent file
+" Language: llvm
+" Maintainer: The LLVM team, http://llvm.org/
+" What this indent plugin currently does:
+" - If no other rule matches copy indent from previous non-empty,
+" non-commented line
+" - On '}' align the same as the line containing the matching '{'
+" - If previous line ends with ':' increase indentation
+" - If the current line ends with ':' indent at the same level as the
+" enclosing '{'/'}' block
+" Stuff that would be nice to add:
+" - Continue comments on next line
+" - If there is an opening+unclosed parenthesis on previous line indent to that
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal shiftwidth=2 expandtab
+
+setlocal indentkeys=0{,0},<:>,!^F,o,O,e
+setlocal indentexpr=GetLLVMIndent()
+
+if exists("*GetLLVMIndent")
+ finish
+endif
+
+function! FindOpenBrace(lnum)
+ call cursor(a:lnum, 1)
+ return searchpair('{', '', '}', 'bW')
+endfun
+
+function! GetLLVMIndent()
+ " On '}' align the same as the line containing the matching '{'
+ let thisline = getline(v:lnum)
+ if thisline =~ '^\s*}'
+ call cursor(v:lnum, 1)
+ silent normal %
+ let opening_lnum = line('.')
+ if opening_lnum != v:lnum
+ return indent(opening_lnum)
+ endif
+ endif
+
+ " Indent labels the same as the current opening block
+ if thisline =~ ':\s*$'
+ let blockbegin = FindOpenBrace(v:lnum)
+ if blockbegin > 0
+ return indent(blockbegin)
+ endif
+ endif
+
+ " Find a non-blank not-completely commented line above the current line.
+ let prev_lnum = prevnonblank(v:lnum - 1)
+ while prev_lnum > 0 && synIDattr(synID(prev_lnum, indent(prev_lnum)+1, 0), "name") =? "string\|comment"
+ let prev_lnum = prevnonblank(prev_lnum-1)
+ endwhile
+ " Hit the start of the file, use zero indent.
+ if prev_lnum == 0
+ return 0
+ endif
+
+ let ind = indent(prev_lnum)
+ let prevline = getline(prev_lnum)
+
+ " Add a 'shiftwidth' after lines that start a block or labels
+ if prevline =~ '{\s*$' || prevline =~ ':\s*$'
+ let ind = ind + &shiftwidth
+ endif
+
+ return ind
+endfunction
diff --git a/syntax/llvm.vim b/syntax/llvm.vim
new file mode 100644
index 00000000..87202ede
--- /dev/null
+++ b/syntax/llvm.vim
@@ -0,0 +1,237 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Vim syntax file
+" Language: llvm
+" Maintainer: The LLVM team, http://llvm.org/
+" Version: $Revision$
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn case match
+
+" Types.
+" Types also include struct, array, vector, etc. but these don't
+" benefit as much from having dedicated highlighting rules.
+syn keyword llvmType void half float double x86_fp80 fp128 ppc_fp128
+syn keyword llvmType label metadata x86_mmx
+syn keyword llvmType type label opaque token
+syn match llvmType /\<i\d\+\>/
+
+" Instructions.
+" The true and false tokens can be used for comparison opcodes, but it's
+" much more common for these tokens to be used for boolean constants.
+syn keyword llvmStatement add addrspacecast alloca and arcp ashr atomicrmw
+syn keyword llvmStatement bitcast br catchpad catchswitch catchret call
+syn keyword llvmStatement cleanuppad cleanupret cmpxchg eq exact extractelement
+syn keyword llvmStatement extractvalue fadd fast fcmp fdiv fence fmul fpext
+syn keyword llvmStatement fptosi fptoui fptrunc free frem fsub getelementptr
+syn keyword llvmStatement icmp inbounds indirectbr insertelement insertvalue
+syn keyword llvmStatement inttoptr invoke landingpad load lshr malloc max min
+syn keyword llvmStatement mul nand ne ninf nnan nsw nsz nuw oeq oge ogt ole
+syn keyword llvmStatement olt one or ord phi ptrtoint resume ret sdiv select
+syn keyword llvmStatement sext sge sgt shl shufflevector sitofp sle slt srem
+syn keyword llvmStatement store sub switch trunc udiv ueq uge ugt uitofp ule ult
+syn keyword llvmStatement umax umin une uno unreachable unwind urem va_arg
+syn keyword llvmStatement xchg xor zext
+
+" Keywords.
+syn keyword llvmKeyword
+ \ acq_rel
+ \ acquire
+ \ addrspace
+ \ alias
+ \ align
+ \ alignstack
+ \ alwaysinline
+ \ appending
+ \ argmemonly
+ \ arm_aapcscc
+ \ arm_aapcs_vfpcc
+ \ arm_apcscc
+ \ asm
+ \ atomic
+ \ available_externally
+ \ blockaddress
+ \ builtin
+ \ byval
+ \ c
+ \ catch
+ \ caller
+ \ cc
+ \ ccc
+ \ cleanup
+ \ coldcc
+ \ comdat
+ \ common
+ \ constant
+ \ datalayout
+ \ declare
+ \ default
+ \ define
+ \ deplibs
+ \ dereferenceable
+ \ distinct
+ \ dllexport
+ \ dllimport
+ \ dso_local
+ \ dso_preemptable
+ \ except
+ \ external
+ \ externally_initialized
+ \ extern_weak
+ \ fastcc
+ \ filter
+ \ from
+ \ gc
+ \ global
+ \ hhvmcc
+ \ hhvm_ccc
+ \ hidden
+ \ initialexec
+ \ inlinehint
+ \ inreg
+ \ inteldialect
+ \ intel_ocl_bicc
+ \ internal
+ \ linkonce
+ \ linkonce_odr
+ \ localdynamic
+ \ localexec
+ \ local_unnamed_addr
+ \ minsize
+ \ module
+ \ monotonic
+ \ msp430_intrcc
+ \ musttail
+ \ naked
+ \ nest
+ \ noalias
+ \ nobuiltin
+ \ nocapture
+ \ noimplicitfloat
+ \ noinline
+ \ nonlazybind
+ \ nonnull
+ \ norecurse
+ \ noredzone
+ \ noreturn
+ \ nounwind
+ \ optnone
+ \ optsize
+ \ personality
+ \ private
+ \ protected
+ \ ptx_device
+ \ ptx_kernel
+ \ readnone
+ \ readonly
+ \ release
+ \ returned
+ \ returns_twice
+ \ sanitize_address
+ \ sanitize_memory
+ \ sanitize_thread
+ \ section
+ \ seq_cst
+ \ sideeffect
+ \ signext
+ \ syncscope
+ \ source_filename
+ \ speculatable
+ \ spir_func
+ \ spir_kernel
+ \ sret
+ \ ssp
+ \ sspreq
+ \ sspstrong
+ \ strictfp
+ \ swiftcc
+ \ tail
+ \ target
+ \ thread_local
+ \ to
+ \ triple
+ \ unnamed_addr
+ \ unordered
+ \ uselistorder
+ \ uselistorder_bb
+ \ uwtable
+ \ volatile
+ \ weak
+ \ weak_odr
+ \ within
+ \ writeonly
+ \ x86_64_sysvcc
+ \ win64cc
+ \ x86_fastcallcc
+ \ x86_stdcallcc
+ \ x86_thiscallcc
+ \ zeroext
+
+" Obsolete keywords.
+syn keyword llvmError getresult begin end
+
+" Misc syntax.
+syn match llvmNoName /[%@!]\d\+\>/
+syn match llvmNumber /-\?\<\d\+\>/
+syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/
+syn match llvmFloat /\<0x\x\+\>/
+syn keyword llvmBoolean true false
+syn keyword llvmConstant zeroinitializer undef null none
+syn match llvmComment /;.*$/
+syn region llvmString start=/"/ skip=/\\"/ end=/"/
+syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/
+syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/
+
+" Named metadata and specialized metadata keywords.
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/
+syn match llvmType /!\zs\a\+\ze\s*(/
+syn match llvmConstant /\<DW_TAG_[a-z_]\+\>/
+syn match llvmConstant /\<DW_ATE_[a-zA-Z_]\+\>/
+syn match llvmConstant /\<DW_OP_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_LANG_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_VIRTUALITY_[a-z_]\+\>/
+syn match llvmConstant /\<DIFlag[A-Za-z]\+\>/
+
+" Syntax-highlight lit test commands and bug numbers.
+syn match llvmSpecialComment /;\s*PR\d*\s*$/
+syn match llvmSpecialComment /;\s*REQUIRES:.*$/
+syn match llvmSpecialComment /;\s*RUN:.*$/
+syn match llvmSpecialComment /;\s*CHECK:.*$/
+syn match llvmSpecialComment "\v;\s*CHECK-(NEXT|NOT|DAG|SAME|LABEL):.*$"
+syn match llvmSpecialComment /;\s*XFAIL:.*$/
+
+if version >= 508 || !exists("did_c_syn_inits")
+ if version < 508
+ let did_c_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink llvmType Type
+ HiLink llvmStatement Statement
+ HiLink llvmNumber Number
+ HiLink llvmComment Comment
+ HiLink llvmString String
+ HiLink llvmLabel Label
+ HiLink llvmKeyword Keyword
+ HiLink llvmBoolean Boolean
+ HiLink llvmFloat Float
+ HiLink llvmNoName Identifier
+ HiLink llvmConstant Constant
+ HiLink llvmSpecialComment SpecialComment
+ HiLink llvmError Error
+ HiLink llvmIdentifier Identifier
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "llvm"
diff --git a/syntax/tablegen.vim b/syntax/tablegen.vim
new file mode 100644
index 00000000..8dd1c59f
--- /dev/null
+++ b/syntax/tablegen.vim
@@ -0,0 +1,58 @@
+if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'llvm') != -1
+ finish
+endif
+
+" Vim syntax file
+" Language: TableGen
+" Maintainer: The LLVM team, http://llvm.org/
+" Version: $Revision$
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+" May be changed if you have a really slow machine
+syntax sync minlines=100
+
+syn case match
+
+syn keyword tgKeyword def let in code dag field include defm foreach
+syn keyword tgType class int string list bit bits multiclass
+
+syn match tgNumber /\<\d\+\>/
+syn match tgNumber /\<\d\+\.\d*\>/
+syn match tgNumber /\<0b[01]\+\>/
+syn match tgNumber /\<0x[0-9a-fA-F]\+\>/
+syn region tgString start=/"/ skip=/\\"/ end=/"/ oneline
+
+syn region tgCode start=/\[{/ end=/}\]/
+
+syn keyword tgTodo contained TODO FIXME
+syn match tgComment /\/\/.*$/ contains=tgTodo
+" Handle correctly imbricated comment
+syn region tgComment2 matchgroup=tgComment2 start=+/\*+ end=+\*/+ contains=tgTodo,tgComment2
+
+if version >= 508 || !exists("did_c_syn_inits")
+ if version < 508
+ let did_c_syn_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ HiLink tgKeyword Statement
+ HiLink tgType Type
+ HiLink tgNumber Number
+ HiLink tgComment Comment
+ HiLink tgComment2 Comment
+ HiLink tgString String
+ " May find a better Hilight group...
+ HiLink tgCode Special
+ HiLink tgTodo Todo
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "tablegen"