aboutsummaryrefslogtreecommitdiff
path: root/lib/base-compiler.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/base-compiler.js')
-rw-r--r--lib/base-compiler.js57
1 files changed, 53 insertions, 4 deletions
diff --git a/lib/base-compiler.js b/lib/base-compiler.js
index 0ea1a53eb..7b19b4149 100644
--- a/lib/base-compiler.js
+++ b/lib/base-compiler.js
@@ -26,6 +26,7 @@ const temp = require('temp'),
path = require('path'),
fs = require('fs-extra'),
denodeify = require('denodeify'),
+ LlvmIrParser = require('./llvm-ir'),
AsmParser = require('./asm-parser'),
utils = require('./utils'),
_ = require('underscore'),
@@ -65,6 +66,7 @@ class BaseCompiler {
this.readFile = denodeify(fs.readFile);
this.stat = denodeify(fs.stat);
this.asm = new AsmParser(this.compilerProps);
+ this.llvmIr = new LlvmIrParser(this.compilerProps);
this.possibleArguments = new CompilerArguments(this.compiler.id);
this.possibleTools = _.values(compilerInfo.tools);
@@ -214,6 +216,29 @@ class BaseCompiler {
.then(this.processAstOutput);
}
+ generateIR(inputFilename, options, filters) {
+ // These options make Clang produce an IR
+ let newOptions = _.filter(options, option => option !== '-fcolor-diagnostics')
+ .concat(this.compiler.irArg);
+
+ let execOptions = this.getDefaultExecOptions();
+ // A higher max output is needed for when the user includes headers
+ execOptions.maxOutput = 1024 * 1024 * 1024;
+
+ return this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions)
+ .then((output) => this.processIrOutput(output, filters));
+ }
+
+ processIrOutput(output, filters) {
+ const irPath = output.inputFilename.replace(path.extname(output.inputFilename), '.ll');
+ if (fs.existsSync(irPath)) {
+ const output = fs.readFileSync(irPath, 'utf-8');
+ // uses same filters as main compiler
+ return this.llvmIr.process(output, filters);
+ }
+ return this.llvmIr.process(output.stdout, filters);
+ }
+
getOutputFilename(dirPath, outputFilebase) {
// NB keep lower case as ldc compiler `tolower`s the output name
return path.join(dirPath, `${outputFilebase}.s`);
@@ -439,6 +464,13 @@ class BaseCompiler {
astPromise = Promise.resolve("");
}
+ let irPromise;
+ if (backendOptions && backendOptions.produceIr && this.compiler.supportsIrView) {
+ irPromise = this.generateIR(inputFilename, options, filters);
+ } else {
+ irPromise = Promise.resolve("");
+ }
+
let gccDumpPromise;
if (backendOptions && backendOptions.produceGccDump && backendOptions.produceGccDump.opened &&
this.compiler.supportsGccDump) {
@@ -450,8 +482,14 @@ class BaseCompiler {
gccDumpPromise = Promise.resolve("");
}
- return Promise.all([asmPromise, astPromise, gccDumpPromise, Promise.all(toolsPromise)])
- .then(([asmResult, astResult, gccDumpResult, toolsPromise]) => {
+ return Promise.all([
+ asmPromise,
+ astPromise,
+ gccDumpPromise,
+ irPromise,
+ Promise.all(toolsPromise)
+ ])
+ .then(([asmResult, astResult, gccDumpResult, irResult, toolsPromise]) => {
asmResult.dirPath = dirPath;
asmResult.compilationOptions = options;
// Here before the check to ensure dump reports even on failure cases
@@ -465,7 +503,7 @@ class BaseCompiler {
asmResult.asm = "<Compilation failed>";
return asmResult;
}
- asmResult.hasOptOutput = false;
+
if (this.compiler.supportsOptOutput && this.optOutputRequested(options)) {
const optPath = path.join(dirPath, `${this.outputFilebase}.opt.yaml`);
if (fs.existsSync(optPath)) {
@@ -477,6 +515,10 @@ class BaseCompiler {
asmResult.hasAstOutput = true;
asmResult.astOutput = astResult;
}
+ if (irResult) {
+ asmResult.hasIrOutput = true;
+ asmResult.irOutput = irResult;
+ }
return this.checkOutputFileAndDoPostProcess(asmResult, outputFilename, filters);
});
@@ -527,7 +569,7 @@ class BaseCompiler {
result.dirPath = undefined;
}
if (result.okToCache) {
- result.asm = this.asm.process(result.asm, filters);
+ result.asm = this.processAsm(result, filters);
} else {
result.asm = [{text: result.asm}];
}
@@ -563,6 +605,13 @@ class BaseCompiler {
});
}
+ processAsm(result, filters) {
+ if (this.llvmIr.isLlvmIr(result.asm)) {
+ return this.llvmIr.process(result.asm, filters);
+ }
+ return this.asm.process(result.asm, filters);
+ }
+
postProcessAsm(result) {
if (!result.okToCache) return result;
const demanglerExe = this.compiler.demangler;