diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1b0394ce1..68c7ca86f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -57,3 +57,4 @@ From oldest to newest contributor, we would like to thank: - [phuclv90](https://github.com/phuclv90) - [Nicole Mazzuca](https://github.com/ubsan) - [Jameson Nash](https://github.com/vtjnash) +- [Marc Tiehuis](https://github.com/tiehuis) diff --git a/etc/config/zig.amazon.properties b/etc/config/zig.amazon.properties new file mode 100644 index 000000000..ab5aeeee7 --- /dev/null +++ b/etc/config/zig.amazon.properties @@ -0,0 +1,15 @@ +compilers=&zig +defaultCompiler=master + +group.zig.compilers=master +group.zig.objdumper=/opt/compiler-explorer/gcc-8.1.0/bin/objdump +group.zig.isSemVer=true +group.zig.baseName=zig + +compiler.master.exe=/opt/compiler-explorer/zig-master/bin/zig +compiler.master.semver=master + +################################# +################################# +# Installed libs (See c++.amazon.properties for a scheme of libs group) +libs= diff --git a/etc/config/zig.defaults.properties b/etc/config/zig.defaults.properties new file mode 100644 index 000000000..8434fa922 --- /dev/null +++ b/etc/config/zig.defaults.properties @@ -0,0 +1,12 @@ +compilers=/usr/bin/zig +supportsBinary=true +compilerType=zig +objdumper=objdump +versionFlag=version +binaryHideFuncRe=^(_.*|call_gmon_start|(de)?register_tm_clones|frame_dummy|.*@plt.*)$ + + +################################# +################################# +# Installed libs (See c++.amazon.properties for a scheme of libs group) +libs= diff --git a/examples/zig/Sum_over_array.zig b/examples/zig/Sum_over_array.zig new file mode 100644 index 000000000..f17e547d2 --- /dev/null +++ b/examples/zig/Sum_over_array.zig @@ -0,0 +1,7 @@ +export fn sumArray(array: [*]const u32, len: usize) u32 { + var sum: u32 = 0; + for (array[0..len]) |item| { + sum += item; + } + return sum; +} diff --git a/examples/zig/default.zig b/examples/zig/default.zig new file mode 100644 index 000000000..0a9229ec3 --- /dev/null +++ b/examples/zig/default.zig @@ -0,0 +1,4 @@ +// Type your code here, or load an example. +export fn square(num: i32) i32 { + return num * num; +} diff --git a/lib/base-compiler.js b/lib/base-compiler.js index 3435133d2..9fe84d3f3 100644 --- a/lib/base-compiler.js +++ b/lib/base-compiler.js @@ -250,6 +250,8 @@ class BaseCompiler { return this.env.cacheGet(key) .then((result) => { if (result) return result; + + source = this.preProcess(source); if (filters.binary && !source.match(this.compilerProps("stubRe"))) { source += "\n" + this.compilerProps("stubText") + "\n"; } @@ -544,6 +546,10 @@ Please select another pass or change filters.`; .then(postResult => this.handlePostProcessResult(result, postResult)); } + preProcess(source) { + return source; + } + postProcess(result, outputFilename, filters) { const postProcess = _.compact(this.compiler.postProcess); const maxSize = this.env.ceProps("max-asm-size", 8 * 1024 * 1024); diff --git a/lib/compilers/zig.js b/lib/compilers/zig.js new file mode 100644 index 000000000..5133b8eb6 --- /dev/null +++ b/lib/compilers/zig.js @@ -0,0 +1,64 @@ +// Copyright (c) 2018, Marc Tiehuis +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +const BaseCompiler = require('../base-compiler'), + _ = require('underscore'), + path = require('path'); + +class ZigCompiler extends BaseCompiler { + constructor(info, env) { + super(info, env); + this.compiler.supportsIntel = true; + } + + preProcess(source) { + source += '\n'; + source += 'extern fn zig_panic() noreturn;\n'; + source += 'pub inline fn panic(msg: []const u8, error_return_trace: ' + + '?*@import("builtin").StackTrace) noreturn {\n'; + source += ' zig_panic();\n'; + source += '}\n'; + + return source; + } + + optionsForFilter(filters, outputFilename, userOptions) { + let options = [ + 'build-obj', + '--cache-dir', path.dirname(outputFilename), + '--output', this.filename(outputFilename) + ]; + + let userRequestedEmit = _.any(userOptions, opt => opt.indexOf("--emit") > -1); + if (!filters.binary) { + if (!userRequestedEmit) { + options = options.concat('--emit', 'asm'); + } + if (filters.intel) options = options.concat('-mllvm', '--x86-asm-syntax=intel'); + } + return options; + } +} + +module.exports = ZigCompiler; diff --git a/lib/languages.js b/lib/languages.js index 7ca57f579..edf8b2f4a 100644 --- a/lib/languages.js +++ b/lib/languages.js @@ -130,7 +130,13 @@ const languages = { monaco: 'cuda', extensions: ['.cu'], alias: ['nvcc'] - } + }, + zig: { + name: 'Zig', + monaco: 'zig', + extensions: ['.zig'], + alias: [] + }, }; const fs = require('fs-extra'); diff --git a/static/modes/zig-mode.js b/static/modes/zig-mode.js new file mode 100644 index 000000000..5c91eb816 --- /dev/null +++ b/static/modes/zig-mode.js @@ -0,0 +1,135 @@ +// Copyright (c) 2018, Marc Tiehuis +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +"use strict"; + +function definition() { + return { + defaultToken: 'invalid', + + keywords: [ + 'const', 'var', 'extern', 'packed', 'export', 'pub', 'noalias', 'inline', + 'comptime', 'nakedcc', 'stdcallcc', 'volatile', 'align', 'section', + 'struct', 'enum', 'union', + 'break', 'return', 'continue', 'asm', 'defer', 'errdefer', 'unreachable', + 'try', 'catch', 'async', 'await', 'suspend', 'resume', 'cancel', + 'if', 'else', 'switch', 'and', 'or', 'orelse', + 'while', 'for', + 'null', 'undefined', 'this', + 'fn', 'use', 'test' + ], + typeKeywords: [ + 'bool', 'f32', 'f64', 'f128', 'void', 'noreturn', 'type', 'error', 'promise', + 'isize', 'usize', 'c_short', 'c_ushort', 'c_int', 'c_uint', 'c_long', 'c_ulong', + 'c_longlong', 'c_ulonglong', 'c_longdouble', 'c_void' + ], + operators: [ + '+', '+%', '-', '-%', '/', '*', '*%', '=', '^', '&', '?', '|', + '!', '>', '<', '%', '<<', '<<%', '>>', + '+=', '+%=', '-=', '-%=', '/=', '*=', '*%=', '==', '^=', '&=', + '?=', '|=', '!=', '>=', '<=', '%=', '<<=', '<<%=', '>>=' + ], + + symbols: /[=>](?!@symbols)/, '@brackets'], + [/@symbols/, { + cases: { + '@operators': 'operator', + '@default': '' + } + }], + + // numbers + [/\d*\.\d+([eE][-+]?\d+)?[fFdD]?/, 'number.float'], + [/0[xX][0-9a-fA-F_]*[0-9a-fA-F][Ll]?/, 'number.hex'], + [/0o[0-7_]*[0-7][Ll]?/, 'number.octal'], + [/0[bB][0-1_]*[0-1][Ll]?/, 'number.binary'], + [/\d+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/c?\\\\.*$/, 'string'], + [/c?"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \r\n]+/, 'white'], + [/\/\*/, 'comment', '@comment'], + [/\/\+/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'], + [/\t/, 'comment.invalid'] + ], + + comment: [ + [/[^/*]+/, 'comment'], + [/\/\*/, 'comment.invalid'], + [/[/*]/, 'comment'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ] + } + }; +} + +monaco.languages.register({id: 'zig'}); +monaco.languages.setMonarchTokensProvider('zig', definition()); diff --git a/static/panes/editor.js b/static/panes/editor.js index b1aaac6a7..d737d325e 100644 --- a/static/panes/editor.js +++ b/static/panes/editor.js @@ -40,6 +40,7 @@ require('../modes/ispc-mode'); require('../modes/haskell-mode'); require('../modes/pascal-mode'); require('../modes/cuda-mode'); +require('../modes/zig-mode'); require('selectize'); var loadSave = new loadSaveLib.LoadSave(); diff --git a/views/head.pug b/views/head.pug index 5b4829b7c..385bedfb9 100644 --- a/views/head.pug +++ b/views/head.pug @@ -8,10 +8,10 @@ if metadata meta(name="description" content=metadata.ogDescription) meta(property="og:description" content=metadata.ogDescription) else - meta(name="description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal & CUDA code.") - meta(property="og:description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal & CUDA code.") + meta(name="description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal, Zig & CUDA code.") + meta(property="og:description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal, Zig & CUDA code.") else - meta(name="description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal & CUDA code.") + meta(name="description" content="Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C, C++, Rust, Go, D, Haskell, Swift, Pascal, Zig & CUDA code.") meta(property="og:title" content="Compiler Explorer") meta(name="twitter:card" content="summary") meta(name="twitter:site" content="@mattgodbolt")