diff options
Diffstat (limited to 'lib/compilers/rust.ts')
-rw-r--r-- | lib/compilers/rust.ts | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/compilers/rust.ts b/lib/compilers/rust.ts new file mode 100644 index 000000000..eb747c8dc --- /dev/null +++ b/lib/compilers/rust.ts @@ -0,0 +1,160 @@ +// Copyright (c) 2016, Compiler Explorer Authors +// 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. + +import path from 'path'; + +import _ from 'underscore'; + +import {BaseCompiler} from '../base-compiler'; +import {BuildEnvDownloadInfo} from '../buildenvsetup/buildenv.interfaces'; +import {logger} from '../logger'; +import {parseRustOutput} from '../utils'; + +import {RustParser} from './argument-parsers'; + +export class RustCompiler extends BaseCompiler { + linker: string; + static get key() { + return 'rust'; + } + + constructor(info, env) { + super(info, env); + this.compiler.supportsIntel = true; + this.compiler.supportsIrView = true; + this.compiler.supportsRustMirView = true; + + const isNightly = info.name === 'nightly' || info.semver === 'nightly'; + // Macro expansion (-Zunpretty=expanded) and HIR (-Zunpretty=hir-tree) + // are only available for Nightly + this.compiler.supportsRustMacroExpView = isNightly; + this.compiler.supportsRustHirView = isNightly; + + this.compiler.irArg = ['--emit', 'llvm-ir']; + this.linker = this.compilerProps('linker'); + } + + override getSharedLibraryPathsAsArguments(libraries, libDownloadPath) { + return []; + } + + override getSharedLibraryLinks(libraries): string[] { + return []; + } + + override getIncludeArguments(libraries) { + const includeFlag = '--extern'; + return _.flatten( + _.map(libraries, selectedLib => { + const foundVersion = this.findLibVersion(selectedLib); + if (!foundVersion) return false; + if (!foundVersion.name) return false; + const list: string[] = []; + const lowercaseLibName = foundVersion.name.replaceAll('-', '_'); + for (const rlib of foundVersion.path) { + list.push( + includeFlag, + `${lowercaseLibName}=${foundVersion.name}/build/debug/${rlib}`, + '-L', + `dependency=${foundVersion.name}/build/debug/deps`, + ); + } + return list; + }), + ); + } + + override orderArguments( + options, + inputFilename, + libIncludes, + libOptions, + libPaths, + libLinks, + userOptions, + staticLibLinks, + ) { + return options.concat(userOptions, libIncludes, libOptions, libPaths, libLinks, staticLibLinks, [ + this.filename(inputFilename), + ]); + } + + override async setupBuildEnvironment(key, dirPath): Promise<BuildEnvDownloadInfo[]> { + if (this.buildenvsetup) { + const libraryDetails = await this.getRequiredLibraryVersions(key.libraries); + return this.buildenvsetup.setup(key, dirPath, libraryDetails); + } else { + return []; + } + } + + override optionsForBackend(backendOptions, outputFilename) { + // The super class handles the GCC dump files that may be needed by + // rustc-cg-gcc subclass. + const opts = super.optionsForBackend(backendOptions, outputFilename); + + if (backendOptions.produceRustMir && this.compiler.supportsRustMirView) { + const of = this.getRustMirOutputFilename(outputFilename); + opts.push('--emit', `mir=${of}`); + } + return opts; + } + + override optionsForFilter(filters, outputFilename, userOptions) { + let options = ['-C', 'debuginfo=1', '-o', this.filename(outputFilename)]; + + const userRequestedEmit = _.any(userOptions, opt => opt.includes('--emit')); + if (filters.binary) { + options = options.concat(['--crate-type', 'bin']); + if (this.linker) { + options = options.concat(`-Clinker=${this.linker}`); + } + } else if (!filters.binary) { + if (!userRequestedEmit) { + options = options.concat('--emit', 'asm'); + } + if (filters.intel) options = options.concat('-Cllvm-args=--x86-asm-syntax=intel'); + options = options.concat(['--crate-type', 'rlib']); + } + return options; + } + + // Override the IR file name method for rustc because the output file is different from clang. + override getIrOutputFilename(inputFilename) { + return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase).replace('.s', '.ll'); + } + + override getArgumentParser() { + return RustParser; + } + + override isCfgCompiler(/*compilerVersion*/) { + return true; + } + + override parseCompilationOutput(result, inputFilename) { + result.stdout = parseRustOutput(result.stdout, inputFilename); + result.stderr = parseRustOutput(result.stderr, inputFilename); + } +} |