aboutsummaryrefslogtreecommitdiff
path: root/lib/compilers
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compilers')
-rw-r--r--lib/compilers/ada.js91
-rw-r--r--lib/compilers/argument-parsers.js174
-rw-r--r--lib/compilers/golang.js139
-rw-r--r--lib/compilers/haskell.js7
-rw-r--r--lib/compilers/ispc.js11
-rw-r--r--lib/compilers/llc.js7
-rw-r--r--lib/compilers/llvm-mca.js7
-rw-r--r--lib/compilers/nvcc.js7
-rw-r--r--lib/compilers/ocaml.js40
-rw-r--r--lib/compilers/opt.js7
-rw-r--r--lib/compilers/pascal.js2
-rw-r--r--lib/compilers/rust.js11
-rw-r--r--lib/compilers/swift.js10
-rw-r--r--lib/compilers/win32-vc.js2
-rw-r--r--lib/compilers/wine-vc.js12
-rw-r--r--lib/compilers/zig.js29
16 files changed, 501 insertions, 55 deletions
diff --git a/lib/compilers/ada.js b/lib/compilers/ada.js
new file mode 100644
index 000000000..26f4d7102
--- /dev/null
+++ b/lib/compilers/ada.js
@@ -0,0 +1,91 @@
+// Copyright (c) 2018, Mitch Kennedy
+// 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'),
+ utils = require('../utils'),
+ path = require("path");
+
+class AdaCompiler extends BaseCompiler {
+ constructor(info, env) {
+ super(info, env);
+ this.supportsOptOutput = false;
+ this.compiler.supportsIntel = true;
+ }
+
+ optionsForFilter(filters, outputFilename) {
+ let options = ['compile',
+ '-g', // enable debugging
+ '-c', // Compile only
+ '-S', // Generate ASM
+ '-fdiagnostics-color=always',
+ '-fverbose-asm', // Geneate verbose ASM showing variables
+ '-cargs', // Compiler Switches for gcc.
+ '-o', // Set the output executable name
+ outputFilename
+ ];
+ if (this.compiler.intelAsm && filters.intel && !filters.binary) {
+ options = options.concat(this.compiler.intelAsm.split(" "));
+ }
+ return options;
+ }
+
+ // I have left the overloaded preProcess method in case there is a
+ // need to any actual pre-processing of the input.
+ // As Ada expects the outermost function name to match the source file name.
+ // The initial solution was to wrap any input in a dummy example procedure,
+ // this however restricts users from including standard library packages, as
+ // Ada mandates that 'with' clauses are placed in the context clause,
+ // which in the case of a single subprogram is outside of its declaration and body.
+ preProcess(source) {
+ return source;
+ }
+
+ runCompiler(compiler, options, inputFilename, execOptions) {
+ if (!execOptions) {
+ execOptions = this.getDefaultExecOptions();
+ }
+ // Set the working directory to be the temp directory that has been created
+ execOptions.customCwd = path.dirname(inputFilename);
+ // As the file name is always appended to the end of the options array we need to
+ // find where the '-cargs' flag is in options. This is to allow us to set the
+ // output as 'output.s' and not end up with 'example.s'. If the output is left
+ // as 'example.s' CE can't find it and thus you get no output.
+ let inputFileName = options.pop();
+ for (let i = 0; i < options.length; i++) {
+ if (options[i] === '-cargs') {
+ options.splice(i, 0, inputFileName);
+ break;
+ }
+ }
+ return this.exec(compiler, options, execOptions)
+ .then(result => {
+ result.inputFilename = inputFilename;
+ result.stdout = utils.parseOutput(result.stdout, inputFilename);
+ result.stderr = utils.parseOutput(result.stderr, inputFilename);
+ return result;
+ });
+ }
+}
+
+module.exports = AdaCompiler;
diff --git a/lib/compilers/argument-parsers.js b/lib/compilers/argument-parsers.js
index 56b5a40cc..0476ad827 100644
--- a/lib/compilers/argument-parsers.js
+++ b/lib/compilers/argument-parsers.js
@@ -27,18 +27,53 @@ const _ = require('underscore'),
utils = require('../utils');
class BaseParser {
+ static hasSupport(options, forOption) {
+ return _.keys(options).find(option => option.includes(forOption));
+ }
+
+ static parseLines(stdout, optionRegex) {
+ let previousOption = false;
+ let options = {};
+
+ utils.eachLine(stdout, line => {
+ const match = line.match(optionRegex);
+ if (!match) {
+ if (previousOption && (line.trim().length !== 0)) {
+ if (options[previousOption].description.endsWith("-"))
+ options[previousOption].description += line.trim();
+ else {
+ if (options[previousOption].description.length !== 0)
+ options[previousOption].description += " " + line.trim();
+ else
+ options[previousOption].description = line.trim();
+ }
+ } else {
+ previousOption = false;
+ }
+ return;
+ }
+
+ if (match) previousOption = match[1];
+ if (previousOption) {
+ options[previousOption] = {
+ description: match[2].trim(),
+ timesused: 0
+ };
+ }
+ });
+
+ return options;
+ }
+
static getOptions(compiler, helpArg) {
return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => {
- const options = {};
+ let options = {};
if (result.code === 0) {
- const optionFinder = /^\s*(--?[-a-zA-Z]+)/;
+ const optionFinder = /^\s*(--?[a-z0-9=+,[\]<>|-]*)\s*(.*)/i;
- utils.eachLine(result.stdout + result.stderr, line => {
- const match = line.match(optionFinder);
- if (!match) return;
- options[match[1]] = true;
- });
+ options = BaseParser.parseLines(result.stdout + result.stderr, optionFinder);
}
+ compiler.possibleArguments.populateOptions(options);
return options;
});
}
@@ -52,16 +87,17 @@ class GCCParser extends BaseParser {
static parse(compiler) {
return Promise.all([
GCCParser.getOptions(compiler, "--target-help"),
- GCCParser.getOptions(compiler, "--help=common")
+ GCCParser.getOptions(compiler, "--help=common"),
+ GCCParser.getOptions(compiler, "--help=optimizers")
]).then(results => {
const options = _.extend.apply(_.extend, results);
const keys = _.keys(options);
logger.debug("gcc-like compiler options: ", keys.join(" "));
- if (options['-masm']) {
+ if (BaseParser.hasSupport(options, "-masm=")) {
compiler.compiler.intelAsm = "-masm=intel";
compiler.compiler.supportsIntel = true;
}
- if (options['-fdiagnostics-color']) {
+ if (BaseParser.hasSupport(options, "-fdiagnostics-color")) {
if (compiler.compiler.options) compiler.compiler.options += " ";
compiler.compiler.options += "-fdiagnostics-color=always";
}
@@ -78,25 +114,135 @@ class ClangParser extends BaseParser {
static parse(compiler) {
return ClangParser.getOptions(compiler, "--help").then(options => {
logger.debug("clang-like compiler options: ", _.keys(options).join(" "));
- if (options['-fsave-optimization-record']) {
+ if (BaseParser.hasSupport(options, '-fsave-optimization-record')) {
compiler.compiler.optArg = "-fsave-optimization-record";
compiler.compiler.supportsOptOutput = true;
}
- if (options['-fcolor-diagnostics']) {
+ if (BaseParser.hasSupport(options, "-fcolor-diagnostics")) {
if (compiler.compiler.options) compiler.compiler.options += " ";
compiler.compiler.options += "-fcolor-diagnostics";
}
- if (options['-emit-llvm']) {
+ if (BaseParser.hasSupport(options, "-emit-llvm")) {
compiler.compiler.supportsIrView = true;
compiler.compiler.irArg = ['-Xclang', '-emit-llvm', '-fsyntax-only'];
}
+ if (BaseParser.hasSupport(options, "-fno-crash-diagnostics")) {
+ if (compiler.compiler.options) compiler.compiler.options += " ";
+ compiler.compiler.options += "-fno-crash-diagnostics";
+ }
return compiler;
});
}
}
+class PascalParser extends BaseParser {
+ static parse(compiler) {
+ return PascalParser.getOptions(compiler, "-help").then(() => compiler);
+ }
+}
+
+class ISPCParser extends BaseParser {
+ static parse(compiler) {
+ return ISPCParser.getOptions(compiler, "--help").then(() => compiler);
+ }
+
+ static getOptions(compiler, helpArg) {
+ return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => {
+ let options = {};
+ if (result.code === 0) {
+ const optionFinder = /^\s*\[(--?[a-z0-9=+,{}\s[\]<>|-]*)\]\s*(.*)/i;
+
+ options = BaseParser.parseLines(result.stdout + result.stderr, optionFinder);
+ }
+ compiler.possibleArguments.populateOptions(options);
+ return options;
+ });
+ }
+}
+
+class VCParser extends BaseParser {
+ static parse(compiler) {
+ return Promise.all([
+ VCParser.getOptions(compiler, "/help")
+ ]).then(() => {
+ return compiler;
+ });
+ }
+
+ static parseLines(stdout, optionRegex) {
+ let previousOption = false;
+ let options = {};
+
+ const matchLine = (line) => {
+ if (line.startsWith("/?")) return;
+
+ const match = line.match(optionRegex);
+ if (!match) {
+ if (previousOption && (line.trim().length !== 0)) {
+ if (options[previousOption].description.endsWith(":"))
+ options[previousOption].description += " " + line.trim();
+ else {
+ if (options[previousOption].description.length !== 0)
+ options[previousOption].description += ", " + line.trim();
+ else
+ options[previousOption].description = line.trim();
+ }
+ } else {
+ previousOption = false;
+ }
+ return;
+ }
+
+ if (match) previousOption = match[1];
+ if (previousOption) {
+ options[previousOption] = {
+ description: match[2].trim(),
+ timesused: 0
+ };
+ }
+ };
+
+ utils.eachLine(stdout, line => {
+ if (line.length === 0) return;
+ if (line.includes("C/C++ COMPILER OPTIONS")) return;
+ if (line.match(/^\s\s*-.*-$/)) return;
+
+ let col1;
+ let col2;
+ if ((line.length > 39) && (line[40] === '/')) {
+ col1 = line.substr(0, 39);
+ col2 = line.substr(40);
+ } else {
+ col1 = line;
+ col2 = "";
+ }
+
+ if (col1) matchLine(col1);
+ if (col2) matchLine(col2);
+ });
+
+ return options;
+ }
+
+ static getOptions(compiler, helpArg) {
+ return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => {
+ let options = {};
+ if (result.code === 0) {
+ const optionFinder = /^\s*(\/[a-z0-9=:+#.,[\]{}<>|_-]*)\s*(.*)/i;
+
+ options = this.parseLines(result.stdout, optionFinder);
+ }
+ compiler.possibleArguments.populateOptions(options);
+ return options;
+ });
+ }
+}
+
module.exports = {
Base: BaseParser,
Clang: ClangParser,
- GCC: GCCParser
+ GCC: GCCParser,
+ VC: VCParser,
+ Pascal: PascalParser,
+ ISPC: ISPCParser
};
diff --git a/lib/compilers/golang.js b/lib/compilers/golang.js
index bbf666576..8c298ad38 100644
--- a/lib/compilers/golang.js
+++ b/lib/compilers/golang.js
@@ -23,41 +23,144 @@
// POSSIBILITY OF SUCH DAMAGE.
const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers"),
_ = require('underscore'),
utils = require('../utils');
+// Each arch has a list of jump instructions in
+// Go source src/cmd/asm/internal/arch.
+const jumpPrefixes = [
+ 'j',
+ 'b',
+
+ // arm
+ 'cb',
+ 'tb',
+
+ // s390x
+ 'cmpb',
+ 'cmpub'
+];
+
class GolangCompiler extends BaseCompiler {
convertNewGoL(code) {
- const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/;
- const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?[0-9]+\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
+ const re = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?([0-9]+)\s*\(([^:]+):([0-9]+)\)\s*([A-Z]+)(.*)/;
+ const reUnknown = /^\s+(0[xX]?[0-9A-Za-z]+)?\s?([0-9]+)\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
+ const reFunc = /TEXT\s+[".]*(\S+)\(SB\)/;
let prevLine = null;
let file = null;
let fileCount = 0;
- return _.compact(code.map(obj => {
+ let func = null;
+ let funcCollisions = {};
+ let labels = {};
+ let usedLabels = {};
+ let lines = code.map(obj => {
+ let pcMatch = null;
+ let fileMatch = null;
+ let lineMatch = null;
+ let ins = null;
+ let args = null;
+
const line = obj.text;
let match = line.match(re);
if (match) {
- let res = "";
- if (file !== match[2]) {
- fileCount++;
- res += "\t.file " + fileCount + ' "' + match[2] + '"\n';
- file = match[2];
- }
- if (prevLine !== match[3]) {
- res += "\t.loc " + fileCount + " " + match[3] + " 0\n";
- prevLine = match[3];
- }
- return res + "\t" + match[4].toLowerCase() + match[5];
+ pcMatch = match[2];
+ fileMatch = match[3];
+ lineMatch = match[4];
+ ins = match[5];
+ args = match[6];
} else {
match = line.match(reUnknown);
if (match) {
- return "\t" + match[2].toLowerCase() + match[3];
+ pcMatch = match[2];
+ ins = match[3];
+ args = match[4];
} else {
return null;
}
}
- })).join("\n");
+ match = line.match(reFunc);
+ if (match) {
+ // Normalize function name.
+ func = match[1].replace(/[.()*]+/g, "_");
+
+ // It's possible for normalized function names to collide.
+ // Keep a count of collisions per function name. Labels get
+ // suffixed with _[collisions] when collisions > 0.
+ let collisions = funcCollisions[func];
+ if (collisions == null) {
+ collisions = 0;
+ } else {
+ collisions++;
+ }
+
+ funcCollisions[func] = collisions;
+ }
+
+ let res = [];
+ if (pcMatch && !labels[pcMatch]) {
+ // Create pseudo-label.
+ let label = pcMatch.replace(/^0{0,4}/, '');
+ let suffix = '';
+ if (funcCollisions[func] > 0) {
+ suffix = `_${funcCollisions[func]}`;
+ }
+
+ label = `${func}_pc${label}${suffix}:`;
+ if (!labels[label]) {
+ res.push(label);
+ labels[label] = true;
+ }
+ }
+
+ if (fileMatch && file !== fileMatch) {
+ fileCount++;
+ res.push(`\t.file ${fileCount} "${fileMatch}"`);
+ file = fileMatch;
+ }
+
+ if (lineMatch && prevLine !== lineMatch) {
+ res.push(`\t.loc ${fileCount} ${lineMatch} 0`);
+ prevLine = lineMatch;
+ }
+
+ ins = ins.toLowerCase();
+ args = this.replaceJump(func, funcCollisions[func], ins, args, usedLabels);
+ res.push(`\t${ins}${args}`);
+ return res;
+ });
+
+ // Find unused pseudo-labels so they can be filtered out.
+ let unusedLabels = _.mapObject(labels, (val, key) => { return !usedLabels[key]; });
+
+ return _.chain(lines)
+ .flatten()
+ .compact()
+ .filter((line) => { return !unusedLabels[line]; })
+ .value()
+ .join("\n");
+ }
+
+ replaceJump(func, collisions, ins, args, usedLabels) {
+ // Check if last argument is a decimal number.
+ const re = /(\s+)([0-9]+)(\s?)$/;
+ let match = args.match(re);
+ if (!match) {
+ return args;
+ }
+
+ // Check instruction has a jump prefix
+ if (_.any(jumpPrefixes, (prefix) => { return ins.startsWith(prefix); })) {
+ let label = `${func}_pc${match[2]}`;
+ if (collisions > 0) {
+ label += `_${collisions}`;
+ }
+ usedLabels[label + ":"] = true; // record label use for later filtering
+ return `${match[1]}${label}${match[3]}`;
+ }
+
+ return args;
}
extractLogging(stdout) {
@@ -90,6 +193,10 @@ class GolangCompiler extends BaseCompiler {
}
return execOptions;
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
module.exports = GolangCompiler;
diff --git a/lib/compilers/haskell.js b/lib/compilers/haskell.js
index 04cc55266..63394b3e7 100644
--- a/lib/compilers/haskell.js
+++ b/lib/compilers/haskell.js
@@ -22,12 +22,17 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class HaskellCompiler extends BaseCompiler {
optionsForFilter(filters, outputFilename) {
return ['-S', '-g', '-o', this.filename(outputFilename)];
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
module.exports = HaskellCompiler;
diff --git a/lib/compilers/ispc.js b/lib/compilers/ispc.js
index fc0373513..bb571dd8a 100644
--- a/lib/compilers/ispc.js
+++ b/lib/compilers/ispc.js
@@ -22,12 +22,21 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class ISPCCompiler extends BaseCompiler {
optionsForFilter(filters, outputFilename) {
return ['--target=sse2-i32x4', '--emit-asm', '-g', '-o', this.filename(outputFilename)];
}
+
+ getArgumentParser() {
+ return argumentParsers.ISPC;
+ }
+
+ isCfgCompiler(/*compilerVersion*/) {
+ return true;
+ }
}
module.exports = ISPCCompiler;
diff --git a/lib/compilers/llc.js b/lib/compilers/llc.js
index 11eb7c855..65b9f58dc 100644
--- a/lib/compilers/llc.js
+++ b/lib/compilers/llc.js
@@ -22,7 +22,8 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class LLCCompiler extends BaseCompiler {
constructor(info, env) {
@@ -36,6 +37,10 @@ class LLCCompiler extends BaseCompiler {
if (filters.binary) options = options.concat('-filetype=obj');
return options;
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
module.exports = LLCCompiler;
diff --git a/lib/compilers/llvm-mca.js b/lib/compilers/llvm-mca.js
index 47e0f91ef..fc8e84b4c 100644
--- a/lib/compilers/llvm-mca.js
+++ b/lib/compilers/llvm-mca.js
@@ -22,7 +22,8 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
-const AnalysisTool = require('./analysis-tool');
+const AnalysisTool = require('./analysis-tool'),
+ argumentParsers = require("./argument-parsers");
// Plain compiler, which just runs the tool and returns whatever the output was
class LLVMmcaTool extends AnalysisTool {
@@ -39,6 +40,10 @@ class LLVMmcaTool extends AnalysisTool {
if (filters.intel) options = options.concat(this.compiler.intelAsm.split(' '));
return options;
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
diff --git a/lib/compilers/nvcc.js b/lib/compilers/nvcc.js
index 73f556baf..c090cb419 100644
--- a/lib/compilers/nvcc.js
+++ b/lib/compilers/nvcc.js
@@ -22,7 +22,8 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class NvccCompiler extends BaseCompiler {
constructor(info, env) {
@@ -38,6 +39,10 @@ class NvccCompiler extends BaseCompiler {
optionsForFilter(filters, outputFilename) {
return ['-o', this.filename(outputFilename), '--ptx', '--generate-line-info'];
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
module.exports = NvccCompiler;
diff --git a/lib/compilers/ocaml.js b/lib/compilers/ocaml.js
new file mode 100644
index 000000000..9c1f12555
--- /dev/null
+++ b/lib/compilers/ocaml.js
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, Eugen Bulavin
+// 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";
+
+const BaseCompiler = require('../base-compiler'),
+ path = require("path");
+
+class OCamlCompiler extends BaseCompiler {
+ optionsForFilter() {
+ return ['-S', '-g', '-c'];
+ }
+
+ getOutputFilename(dirPath) {
+ return path.join(dirPath, `${path.basename(this.compileFilename, this.lang.extensions[0])}.s`);
+ }
+}
+
+module.exports = OCamlCompiler;
diff --git a/lib/compilers/opt.js b/lib/compilers/opt.js
index c34a28a4c..7a833bad6 100644
--- a/lib/compilers/opt.js
+++ b/lib/compilers/opt.js
@@ -22,7 +22,8 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class OptCompiler extends BaseCompiler {
constructor(info, env) {
@@ -32,6 +33,10 @@ class OptCompiler extends BaseCompiler {
optionsForFilter(filters, outputFilename) {
return ['-o', this.filename(outputFilename), '-S'];
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
}
module.exports = OptCompiler;
diff --git a/lib/compilers/pascal.js b/lib/compilers/pascal.js
index 02e1a4ea5..d9f027749 100644
--- a/lib/compilers/pascal.js
+++ b/lib/compilers/pascal.js
@@ -156,7 +156,7 @@ class FPCCompiler extends BaseCompiler {
}
getArgumentParser() {
- return argumentParsers.Base;
+ return argumentParsers.Pascal;
}
getExtraAsmHint(asm) {
diff --git a/lib/compilers/rust.js b/lib/compilers/rust.js
index 63eec2af7..b0e51635c 100644
--- a/lib/compilers/rust.js
+++ b/lib/compilers/rust.js
@@ -23,7 +23,8 @@
// POSSIBILITY OF SUCH DAMAGE.
const BaseCompiler = require('../base-compiler'),
- _ = require('underscore');
+ _ = require('underscore'),
+ argumentParsers = require("./argument-parsers");
class RustCompiler extends BaseCompiler {
constructor(info, env) {
@@ -45,6 +46,14 @@ class RustCompiler extends BaseCompiler {
options = options.concat(['--crate-type', 'rlib']);
return options;
}
+
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
+
+ isCfgCompiler(/*compilerVersion*/) {
+ return true;
+ }
}
module.exports = RustCompiler;
diff --git a/lib/compilers/swift.js b/lib/compilers/swift.js
index ff43f76f2..71934d7e8 100644
--- a/lib/compilers/swift.js
+++ b/lib/compilers/swift.js
@@ -22,9 +22,17 @@
// 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');
+const BaseCompiler = require('../base-compiler'),
+ argumentParsers = require("./argument-parsers");
class SwiftCompiler extends BaseCompiler {
+ getArgumentParser() {
+ return argumentParsers.Clang;
+ }
+
+ isCfgCompiler(/*compilerVersion*/) {
+ return true;
+ }
}
module.exports = SwiftCompiler;
diff --git a/lib/compilers/win32-vc.js b/lib/compilers/win32-vc.js
index d26ef5778..1a109445f 100644
--- a/lib/compilers/win32-vc.js
+++ b/lib/compilers/win32-vc.js
@@ -33,7 +33,7 @@ class Win32VcCompiler extends Win32Compiler {
}
getArgumentParser() {
- return argumentParsers.Base;
+ return argumentParsers.VC;
}
}
diff --git a/lib/compilers/wine-vc.js b/lib/compilers/wine-vc.js
index 6cd2a282a..640f27427 100644
--- a/lib/compilers/wine-vc.js
+++ b/lib/compilers/wine-vc.js
@@ -52,8 +52,18 @@ class WineVcCompiler extends BaseCompiler {
return 'Z:' + fn;
}
+ runCompiler(compiler, options, inputFilename, execOptions) {
+ if (!execOptions) {
+ execOptions = this.getDefaultExecOptions();
+ }
+
+ execOptions.customCwd = path.dirname(inputFilename).substr(2);
+
+ return super.runCompiler(compiler, options, inputFilename, execOptions);
+ }
+
getArgumentParser() {
- return argumentParsers.Base;
+ return argumentParsers.VC;
}
getExecutableFilename(dirPath, outputFilebase) {
diff --git a/lib/compilers/zig.js b/lib/compilers/zig.js
index 52e67c8b0..ff2b6f6e0 100644
--- a/lib/compilers/zig.js
+++ b/lib/compilers/zig.js
@@ -24,7 +24,8 @@
const BaseCompiler = require('../base-compiler'),
_ = require('underscore'),
- path = require('path');
+ path = require('path'),
+ Semver = require('semver');
class ZigCompiler extends BaseCompiler {
constructor(info, env) {
@@ -53,21 +54,17 @@ class ZigCompiler extends BaseCompiler {
}
optionsForFilter(filters, outputFilename, userOptions) {
- let options;
- if (filters.execute) {
- options = [
- 'build-exe',
- '--cache-dir', path.dirname(outputFilename),
- '--output', this.filename(outputFilename),
- '--output-h', '/dev/null'
- ];
+ let options = [filters.execute ? 'build-exe' : 'build-obj'];
+ if (this.compiler.semver === 'trunk' || Semver.gt(this.compiler.semver, '0.3.0')) {
+ const outputDir = path.dirname(outputFilename);
+ options.push('--cache-dir', outputDir,
+ '--output-dir', outputDir,
+ '--name', path.basename(outputFilename, '.s'));
} else {
- options = [
- 'build-obj',
- '--cache-dir', path.dirname(outputFilename),
+ // Older versions use a different command line interface (#1304)
+ options.push('--cache-dir', path.dirname(outputFilename),
'--output', this.filename(outputFilename),
- '--output-h', '/dev/null'
- ];
+ '--output-h', '/dev/null');
}
if (!filters.binary) {
@@ -84,6 +81,10 @@ class ZigCompiler extends BaseCompiler {
const blacklist = /^(((--(cache-dir|name|output|verbose))|(-mllvm)).*)$/;
return _.filter(userOptions, option => !blacklist.test(option));
}
+
+ isCfgCompiler(/*compilerVersion*/) {
+ return true;
+ }
}
module.exports = ZigCompiler;