mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 09:23:52 -05:00
Add ClangIR compilation options (#6914)
This patch adds two options to the clangir pane that affects the clangir compilation pipeline: * Flat CIR enables the emission of flat clangir CFG; * -fclangir-mem2reg enables the mem2reg pass on the flat clangir CFG.
This commit is contained in:
@@ -33,6 +33,7 @@ import _ from 'underscore';
|
||||
import {unique} from '../shared/common-utils.js';
|
||||
import {PPOptions} from '../static/panes/pp-view.interfaces.js';
|
||||
import {ParsedAsmResultLine} from '../types/asmresult/asmresult.interfaces.js';
|
||||
import {ClangirBackendOptions} from '../types/compilation/clangir.interfaces.js';
|
||||
import {
|
||||
ActiveTool,
|
||||
BuildResult,
|
||||
@@ -1411,13 +1412,23 @@ export class BaseCompiler implements ICompiler {
|
||||
return utils.changeExtension(inputFilename, '.cir');
|
||||
}
|
||||
|
||||
async generateClangir(inputFilename: string, options: string[]): Promise<ResultLine[]> {
|
||||
async generateClangir(
|
||||
inputFilename: string,
|
||||
options: string[],
|
||||
clangirOptions: ClangirBackendOptions,
|
||||
): Promise<ResultLine[]> {
|
||||
const outputFilename = this.getClangirOutputFilename(inputFilename);
|
||||
|
||||
let newOptions = [...options];
|
||||
const newOptions = [...options];
|
||||
if (clangirOptions.flatCFG) {
|
||||
newOptions.push('-Xclang', '-emit-cir-flat');
|
||||
} else {
|
||||
newOptions.push('-Xclang', '-emit-cir');
|
||||
}
|
||||
|
||||
// Replace `-o <name>.s` with `-o <name>.cir`
|
||||
newOptions.splice(options.indexOf('-o'), 2);
|
||||
newOptions = newOptions.concat(['-Xclang', '-emit-cir', '-o', outputFilename]);
|
||||
newOptions.push('-o', outputFilename);
|
||||
|
||||
const execOptions = this.getDefaultExecOptions();
|
||||
const output = await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions);
|
||||
@@ -2358,7 +2369,7 @@ export class BaseCompiler implements ICompiler {
|
||||
filters,
|
||||
)
|
||||
: undefined,
|
||||
makeClangir ? this.generateClangir(inputFilename, options) : undefined,
|
||||
makeClangir ? this.generateClangir(inputFilename, options, backendOptions.produceClangir) : undefined,
|
||||
makeOptPipeline
|
||||
? this.generateOptPipeline(inputFilename, options, filters, backendOptions.produceOptPipeline)
|
||||
: undefined,
|
||||
|
||||
@@ -33,6 +33,7 @@ import {CompilerInfo} from '../types/compiler.interfaces.js';
|
||||
import {CompilationResult} from '../types/compilation/compilation.interfaces.js';
|
||||
import {OptPipelineBackendOptions} from './compilation/opt-pipeline-output.interfaces.js';
|
||||
import {LLVMIrBackendOptions} from './compilation/ir.interfaces.js';
|
||||
import {ClangirBackendOptions} from './compilation/clangir.interfaces.js';
|
||||
import {NewToolSettings, ToolState} from './components.interfaces.js';
|
||||
|
||||
// This list comes from executing
|
||||
@@ -117,6 +118,7 @@ export type EventMap = {
|
||||
optPipelineViewOpened: (compilerId: number) => void;
|
||||
optPipelineViewOptionsUpdated: (compilerId: number, options: OptPipelineBackendOptions, recompile: boolean) => void;
|
||||
llvmIrViewOptionsUpdated: (compilerId: number, options: LLVMIrBackendOptions, recompile: boolean) => void;
|
||||
clangirViewOptionsUpdated: (compilerId: number, options: ClangirBackendOptions, recompile: boolean) => void;
|
||||
languageChange: (editorId: number | boolean, newLangId: LanguageKey, treeId?: boolean | number) => void;
|
||||
modifySettings: (modifiedSettings: Partial<SiteSettings>) => void;
|
||||
motd: (data: Motd) => void;
|
||||
|
||||
@@ -35,13 +35,21 @@ import {extendConfig} from '../monaco-config.js';
|
||||
import {Hub} from '../hub.js';
|
||||
import {CompilationResult} from '../compilation/compilation.interfaces.js';
|
||||
import {CompilerInfo} from '../compiler.interfaces.js';
|
||||
import {Toggles} from '../widgets/toggles.js';
|
||||
import {ClangirBackendOptions} from '../../types/compilation/clangir.interfaces.js';
|
||||
|
||||
export class Clangir extends MonacoPane<monaco.editor.IStandaloneCodeEditor, ClangirState> {
|
||||
private options: Toggles;
|
||||
private lastOptions: ClangirBackendOptions = {
|
||||
flatCFG: false,
|
||||
};
|
||||
|
||||
constructor(hub: Hub, container: Container, state: ClangirState & MonacoPaneState) {
|
||||
super(hub, container, state);
|
||||
if (state.clangirOutput) {
|
||||
this.showClangirResults(state.clangirOutput);
|
||||
}
|
||||
this.onOptionsChange(true);
|
||||
}
|
||||
|
||||
override getInitialHTML(): string {
|
||||
@@ -68,6 +76,12 @@ export class Clangir extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Cla
|
||||
return 'ClangIR Viewer';
|
||||
}
|
||||
|
||||
override registerButtons(state: ClangirState): void {
|
||||
super.registerButtons(state);
|
||||
this.options = new Toggles(this.domRoot.find('.options'), state as unknown as Record<string, boolean>);
|
||||
this.options.on('change', this.onOptionsChange.bind(this));
|
||||
}
|
||||
|
||||
override registerCallbacks(): void {
|
||||
const throttleFunction = _.throttle(
|
||||
(event: monaco.editor.ICursorSelectionChangedEvent) => this.onDidChangeCursorSelection(event),
|
||||
@@ -78,6 +92,31 @@ export class Clangir extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Cla
|
||||
this.eventHub.emit('requestSettings');
|
||||
}
|
||||
|
||||
override getCurrentState(): MonacoPaneState {
|
||||
return {
|
||||
...super.getCurrentState(),
|
||||
...this.options.get(),
|
||||
};
|
||||
}
|
||||
|
||||
onOptionsChange(force = false) {
|
||||
const options = this.options.get();
|
||||
const newOptions: ClangirBackendOptions = {
|
||||
flatCFG: options['flat-cfg'],
|
||||
};
|
||||
let changed = false;
|
||||
for (const k in newOptions) {
|
||||
if (newOptions[k] !== this.lastOptions[k]) {
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.lastOptions = newOptions;
|
||||
if (changed || force) {
|
||||
this.eventHub.emit('clangirViewOptionsUpdated', this.compilerInfo.compilerId, newOptions, true);
|
||||
}
|
||||
}
|
||||
|
||||
override onCompileResult(compilerId: number, compiler: CompilerInfo, result: CompilationResult): void {
|
||||
if (this.compilerInfo.compilerId !== compilerId) return;
|
||||
if (result.clangirOutput) {
|
||||
|
||||
@@ -80,6 +80,7 @@ import {LLVMIrBackendOptions} from '../compilation/ir.interfaces.js';
|
||||
import {InstructionSet} from '../instructionsets.js';
|
||||
import {escapeHTML} from '../../shared/common-utils.js';
|
||||
import {CompilerVersionInfo, setCompilerVersionPopoverForPane} from '../widgets/compiler-version-info.js';
|
||||
import {ClangirBackendOptions} from '../compilation/clangir.interfaces.js';
|
||||
import {LanguageKey} from '../languages.interfaces.js';
|
||||
|
||||
const toolIcons = require.context('../../views/resources/logos', false, /\.(png|svg)$/);
|
||||
@@ -268,6 +269,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
private haskellCmmViewOpen: boolean;
|
||||
private ppOptions: PPOptions;
|
||||
private llvmIrOptions: LLVMIrBackendOptions;
|
||||
private clangirOptions: ClangirBackendOptions;
|
||||
private optPipelineOptions: OptPipelineBackendOptions;
|
||||
private isOutputOpened: boolean;
|
||||
private mouseMoveThrottledFunction?: ((e: monaco.editor.IEditorMouseEvent) => void) & _.Cancelable;
|
||||
@@ -1273,7 +1275,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
produceGnatDebugTree: this.gnatDebugTreeViewOpen,
|
||||
produceGnatDebug: this.gnatDebugViewOpen,
|
||||
produceIr: this.irViewOpen ? this.llvmIrOptions : null,
|
||||
produceClangir: this.clangirViewOpen,
|
||||
produceClangir: this.clangirViewOpen ? this.clangirOptions : null,
|
||||
produceOptPipeline: this.optPipelineViewOpenCount > 0 ? this.optPipelineOptions : null,
|
||||
produceDevice: this.deviceViewOpen,
|
||||
produceRustMir: this.rustMirViewOpen,
|
||||
@@ -2204,6 +2206,15 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
}
|
||||
}
|
||||
|
||||
onClangirViewOptionsUpdated(id: number, options: ClangirBackendOptions, recompile: boolean): void {
|
||||
if (this.id === id) {
|
||||
this.clangirOptions = options;
|
||||
if (recompile) {
|
||||
this.compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOptPipelineViewOpened(id: number): void {
|
||||
if (this.id === id) {
|
||||
this.optPipelineViewOpenCount++;
|
||||
@@ -3001,6 +3012,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
this.eventHub.on('clangirViewOpened', this.onClangirViewOpened, this);
|
||||
this.eventHub.on('clangirViewClosed', this.onClangirViewClosed, this);
|
||||
this.eventHub.on('llvmIrViewOptionsUpdated', this.onLLVMIrViewOptionsUpdated, this);
|
||||
this.eventHub.on('clangirViewOptionsUpdated', this.onClangirViewOptionsUpdated, this);
|
||||
this.eventHub.on('optPipelineViewOpened', this.onOptPipelineViewOpened, this);
|
||||
this.eventHub.on('optPipelineViewClosed', this.onOptPipelineViewClosed, this);
|
||||
this.eventHub.on('optPipelineViewOptionsUpdated', this.onOptPipelineViewOptionsUpdated, this);
|
||||
|
||||
27
types/compilation/clangir.interfaces.ts
Normal file
27
types/compilation/clangir.interfaces.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2023, 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.
|
||||
|
||||
export type ClangirBackendOptions = {
|
||||
flatCFG: boolean;
|
||||
};
|
||||
@@ -38,6 +38,7 @@ import {ResultLine} from '../resultline/resultline.interfaces.js';
|
||||
import {Artifact, ToolResult} from '../tool.interfaces.js';
|
||||
|
||||
import {CFGResult} from './cfg.interfaces.js';
|
||||
import {ClangirBackendOptions} from './clangir.interfaces.js';
|
||||
import {ConfiguredOverrides} from './compiler-overrides.interfaces.js';
|
||||
import {LLVMIrBackendOptions} from './ir.interfaces.js';
|
||||
import {OptPipelineBackendOptions, OptPipelineOutput} from './opt-pipeline-output.interfaces.js';
|
||||
@@ -103,7 +104,7 @@ export type CompilationRequestOptions = {
|
||||
produceGnatDebugTree?: boolean;
|
||||
produceGnatDebug?: boolean;
|
||||
produceIr?: LLVMIrBackendOptions | null;
|
||||
produceClangir?: boolean;
|
||||
produceClangir?: ClangirBackendOptions | null;
|
||||
produceOptPipeline?: OptPipelineBackendOptions | null;
|
||||
produceDevice?: boolean;
|
||||
produceRustMir?: boolean;
|
||||
|
||||
17
views/templates/panes/clangir.pug
Normal file
17
views/templates/panes/clangir.pug
Normal file
@@ -0,0 +1,17 @@
|
||||
mixin optionButton(bind, isActive, text, title)
|
||||
.button-checkbox
|
||||
button(type="button" class="dropdown-item btn btn-sm btn-light" + (isActive ? " active" : "") title=title data-bind=bind aria-pressed=isActive ? "true" : "false")
|
||||
span #{text}
|
||||
input.d-none(type="checkbox" checked=isActive)
|
||||
|
||||
#clangir
|
||||
.top-bar.btn-toolbar.bg-light(role="toolbar")
|
||||
include ../../font-size
|
||||
.btn-group.btn-group-sm.options(role="group")
|
||||
button.btn.btn-sm.btn-light.dropdown-toggle(type="button" title="ClangIR Options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Set output options")
|
||||
span.fas.fa-anchor
|
||||
span.hideable Options
|
||||
.dropdown-menu
|
||||
+optionButton("flat-cfg", false, "Output Flat ClangIR", "Emit flat ClangIR")
|
||||
div.clangir-body
|
||||
.monaco-placeholder
|
||||
@@ -22,6 +22,8 @@ mixin monacopane(id)
|
||||
|
||||
include panes/ir
|
||||
|
||||
include panes/clangir
|
||||
|
||||
include panes/opt-view
|
||||
|
||||
include panes/opt-pipeline
|
||||
@@ -64,8 +66,6 @@ mixin monacopane(id)
|
||||
|
||||
+monacopane("ast")
|
||||
|
||||
+monacopane("clangir")
|
||||
|
||||
+monacopane("tool-input")
|
||||
|
||||
+monacopane("gnatdebugtree")
|
||||
|
||||
Reference in New Issue
Block a user