diff options
Diffstat (limited to 'lib/base-compiler.js')
-rw-r--r-- | lib/base-compiler.js | 57 |
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; |