aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.yml2
-rw-r--r--docs/API.md15
-rw-r--r--lib/base-compiler.ts69
-rw-r--r--lib/compilers/java.ts3
-rw-r--r--lib/compilers/kotlin.ts3
-rw-r--r--lib/compilers/win32-mingw-clang.ts11
-rw-r--r--lib/compilers/win32-mingw-gcc.ts11
-rw-r--r--lib/handlers/compile.interfaces.ts6
-rw-r--r--lib/handlers/compile.ts25
-rw-r--r--lib/llvm-ir.ts4
-rw-r--r--static/compiler-service.ts6
-rw-r--r--static/panes/compiler-request.interfaces.ts68
-rw-r--r--static/panes/compiler.ts19
-rw-r--r--static/panes/device-view.ts1
-rw-r--r--static/panes/executor.ts41
-rw-r--r--static/styles/explorer.scss5
-rw-r--r--static/styles/themes/dark-theme.scss12
-rw-r--r--static/styles/themes/default-theme.scss12
-rw-r--r--static/styles/themes/pink-theme.scss12
-rw-r--r--test/handlers/compile-tests.js3
-rw-r--r--types/compilation/compilation.interfaces.ts87
-rw-r--r--types/compiler.interfaces.ts3
-rw-r--r--types/features/filters.interfaces.ts30
-rw-r--r--views/templates/panes/executor.pug6
24 files changed, 274 insertions, 180 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 87e46521b..f1f890528 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -44,7 +44,7 @@ rules:
import/first: error
import/newline-after-import: error
import/no-absolute-path: error
- import/no-cycle: error
+ #import/no-cycle: error # TODO(jeremy-rifkin) disabled for now due to compilation types
import/no-default-export: error
import/no-deprecated: error
import/no-mutable-exports: error
diff --git a/docs/API.md b/docs/API.md
index d95adc06d..d96707e78 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -121,7 +121,20 @@ The filters are a JSON object with `true`/`false` values. If not supplied, defau
filters override their default values. The `compilerOptions` is used to pass extra arguments to the back end, and is
probably not useful for most REST users.
-To force a cache bypass, set `bypassCache` in the root of the request to `true`.
+To force a cache bypass, `bypassCache` can be set. This accepts an enum value according to:
+
+```ts
+export enum BypassCache {
+ None = 0,
+ Compilation = 1,
+ Execution = 2,
+}
+```
+
+If bypass compile cache is specified and an execution is to happen, the execution cache will also be bypassed.
+
+Note: `bypassCache` previously accepted a boolean. The enum values have been carefully chosen for backwards
+compatibility.
Filters include `binary`, `binaryObject`, `labels`, `intel`, `directives` and `demangle`, which correspond to the UI
buttons on the HTML version.
diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts
index d72adeda6..77aff9750 100644
--- a/lib/base-compiler.ts
+++ b/lib/base-compiler.ts
@@ -29,15 +29,18 @@ import * as PromClient from 'prom-client';
import temp from 'temp';
import _ from 'underscore';
-import type {
+import {
BufferOkFunc,
BuildResult,
BuildStep,
+ BypassCache,
CompilationCacheKey,
CompilationInfo,
CompilationResult,
CustomInputForTool,
ExecutionOptions,
+ bypassCompilationCache,
+ bypassExecutionCache,
} from '../types/compilation/compilation.interfaces.js';
import type {
LLVMOptPipelineBackendOptions,
@@ -489,7 +492,7 @@ export class BaseCompiler implements ICompiler {
maxSize: number,
intelAsm,
demangle,
- staticReloc: boolean,
+ staticReloc: boolean | undefined,
dynamicReloc: boolean,
filters: ParseFiltersAndOutputOptions,
) {
@@ -1718,11 +1721,13 @@ export class BaseCompiler implements ICompiler {
};
}
- async getOrBuildExecutable(key) {
+ async getOrBuildExecutable(key, bypassCache: BypassCache) {
const dirPath = await this.newTempDir();
- const buildResults = await this.loadPackageWithExecutable(key, dirPath);
- if (buildResults) return buildResults;
+ if (!bypassCompilationCache(bypassCache)) {
+ const buildResults = await this.loadPackageWithExecutable(key, dirPath);
+ if (buildResults) return buildResults;
+ }
let compilationResult;
try {
@@ -1843,9 +1848,11 @@ export class BaseCompiler implements ICompiler {
};
}
- async handleExecution(key, executeParameters): Promise<CompilationResult> {
- if (this.compiler.interpreted) return this.handleInterpreting(key, executeParameters);
- const buildResult = await this.getOrBuildExecutable(key);
+ async doExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
+ if (this.compiler.interpreted) {
+ return this.handleInterpreting(key, executeParameters);
+ }
+ const buildResult = await this.getOrBuildExecutable(key, bypassCache);
if (buildResult.code !== 0) {
return {
code: -1,
@@ -1892,6 +1899,23 @@ export class BaseCompiler implements ICompiler {
};
}
+ async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
+ // stringify now so shallow copying isn't a problem, I think the executeParameters get modified
+ const execKey = JSON.stringify({key, executeParameters});
+ if (!bypassExecutionCache(bypassCache)) {
+ const cacheResult = await this.env.cacheGet(execKey as any);
+ if (cacheResult) {
+ return cacheResult;
+ }
+ }
+
+ const result = await this.doExecution(key, executeParameters, bypassCache);
+ if (!bypassExecutionCache(bypassCache)) {
+ await this.env.cachePut(execKey, result, undefined);
+ }
+ return result;
+ }
+
getCacheKey(source, options, backendOptions, filters, tools, libraries, files) {
return {compiler: this.compiler, source, options, backendOptions, filters, tools, libraries, files};
}
@@ -2262,7 +2286,7 @@ export class BaseCompiler implements ICompiler {
}
}
- async cmake(files, key) {
+ async cmake(files, key, bypassCache: BypassCache) {
// key = {source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries};
if (!this.compiler.supportsBinary) {
@@ -2300,7 +2324,9 @@ export class BaseCompiler implements ICompiler {
const outputFilename = this.getExecutableFilename(path.join(dirPath, 'build'), this.outputFilebase, key);
- let fullResult = await this.loadPackageWithExecutable(cacheKey, dirPath);
+ let fullResult = !bypassExecutionCache(bypassCache)
+ ? await this.loadPackageWithExecutable(cacheKey, dirPath)
+ : null;
if (fullResult) {
fullResult.fetchedFromCache = true;
@@ -2421,6 +2447,7 @@ export class BaseCompiler implements ICompiler {
cacheKey.filters,
libsAndOptions.options,
optOutput,
+ bypassCache,
path.join(dirPath, 'build'),
);
@@ -2469,7 +2496,17 @@ export class BaseCompiler implements ICompiler {
}
}
- async compile(source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries, files) {
+ async compile(
+ source,
+ options,
+ backendOptions,
+ filters,
+ bypassCache: BypassCache,
+ tools,
+ executionParameters,
+ libraries,
+ files,
+ ) {
const optionsError = this.checkOptions(options);
if (optionsError) throw optionsError;
const sourceError = this.checkSource(source);
@@ -2494,7 +2531,7 @@ export class BaseCompiler implements ICompiler {
filters = Object.assign({}, filters);
filters.execute = false;
- if (!bypassCache) {
+ if (!bypassCompilationCache(bypassCache)) {
const cacheRetreiveTimeStart = process.hrtime.bigint();
// TODO: We should be able to eliminate this any cast. `key` should be cacheable (if it's not that's a big
// problem) Because key coantains a CompilerInfo which contains a function member it can't be assigned to a
@@ -2512,7 +2549,7 @@ export class BaseCompiler implements ICompiler {
result.execResult = await this.env.enqueue(async () => {
const start = performance.now();
executionQueueTimeHistogram.observe((start - queueTime) / 1000);
- const res = await this.handleExecution(key, executeParameters);
+ const res = await this.handleExecution(key, executeParameters, bypassCache);
executionTimeHistogram.observe((performance.now() - start) / 1000);
return res;
});
@@ -2532,7 +2569,7 @@ export class BaseCompiler implements ICompiler {
source = this.preProcess(source, filters);
if (backendOptions.executorRequest) {
- const execResult = await this.handleExecution(key, executeParameters);
+ const execResult = await this.handleExecution(key, executeParameters, bypassCache);
if (execResult && execResult.buildResult) {
this.doTempfolderCleanup(execResult.buildResult);
}
@@ -2570,6 +2607,7 @@ export class BaseCompiler implements ICompiler {
filters,
options,
optOutput,
+ bypassCache,
);
})();
compilationTimeHistogram.observe((performance.now() - start) / 1000);
@@ -2587,10 +2625,11 @@ export class BaseCompiler implements ICompiler {
filters,
options,
optOutput,
+ bypassCache: BypassCache,
customBuildPath?,
) {
// Start the execution as soon as we can, but only await it at the end.
- const execPromise = doExecute ? this.handleExecution(key, executeParameters) : null;
+ const execPromise = doExecute ? this.handleExecution(key, executeParameters, bypassCache) : null;
if (result.hasOptOutput) {
delete result.optPath;
diff --git a/lib/compilers/java.ts b/lib/compilers/java.ts
index 320469f6e..c01940c57 100644
--- a/lib/compilers/java.ts
+++ b/lib/compilers/java.ts
@@ -35,6 +35,7 @@ import {logger} from '../logger.js';
import * as utils from '../utils.js';
import {JavaParser} from './argument-parsers.js';
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
export class JavaCompiler extends BaseCompiler {
static get key() {
@@ -128,7 +129,7 @@ export class JavaCompiler extends BaseCompiler {
}
override async handleInterpreting(key, executeParameters) {
- const compileResult = await this.getOrBuildExecutable(key);
+ const compileResult = await this.getOrBuildExecutable(key, BypassCache.None);
if (compileResult.code === 0) {
executeParameters.args = [
'-Xss136K', // Reduce thread stack size
diff --git a/lib/compilers/kotlin.ts b/lib/compilers/kotlin.ts
index 0b5cce585..9b1bab103 100644
--- a/lib/compilers/kotlin.ts
+++ b/lib/compilers/kotlin.ts
@@ -22,6 +22,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -98,7 +99,7 @@ export class KotlinCompiler extends JavaCompiler {
...key,
options: ['-include-runtime', '-d', 'example.jar'],
};
- const compileResult = await this.getOrBuildExecutable(alteredKey);
+ const compileResult = await this.getOrBuildExecutable(alteredKey, BypassCache.None);
executeParameters.args = [
'-Xss136K', // Reduce thread stack size
'-XX:CICompilerCount=2', // Reduce JIT compilation threads. 2 is minimum
diff --git a/lib/compilers/win32-mingw-clang.ts b/lib/compilers/win32-mingw-clang.ts
index 83c98c52e..47a6159a8 100644
--- a/lib/compilers/win32-mingw-clang.ts
+++ b/lib/compilers/win32-mingw-clang.ts
@@ -24,7 +24,12 @@
import path from 'path';
-import {BuildResult, CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import {
+ BuildResult,
+ BypassCache,
+ CompilationResult,
+ ExecutionOptions,
+} from '../../types/compilation/compilation.interfaces.js';
import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
import {copyNeededDlls} from '../win-utils.js';
@@ -102,8 +107,8 @@ export class Win32MingWClang extends ClangCompiler {
return result;
}
- override async handleExecution(key, executeParameters): Promise<CompilationResult> {
+ override async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
const execOptions = this.getDefaultExecOptions();
- return super.handleExecution(key, {...executeParameters, env: execOptions.env});
+ return super.handleExecution(key, {...executeParameters, env: execOptions.env}, bypassCache);
}
}
diff --git a/lib/compilers/win32-mingw-gcc.ts b/lib/compilers/win32-mingw-gcc.ts
index 4e3106bc5..04b43f985 100644
--- a/lib/compilers/win32-mingw-gcc.ts
+++ b/lib/compilers/win32-mingw-gcc.ts
@@ -24,7 +24,12 @@
import path from 'path';
-import {BuildResult, CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import {
+ BuildResult,
+ BypassCache,
+ CompilationResult,
+ ExecutionOptions,
+} from '../../types/compilation/compilation.interfaces.js';
import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
import {copyNeededDlls} from '../win-utils.js';
@@ -102,8 +107,8 @@ export class Win32MingWGcc extends GCCCompiler {
return result;
}
- override async handleExecution(key, executeParameters): Promise<CompilationResult> {
+ override async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
const execOptions = this.getDefaultExecOptions();
- return super.handleExecution(key, {...executeParameters, env: execOptions.env});
+ return super.handleExecution(key, {...executeParameters, env: execOptions.env}, bypassCache);
}
}
diff --git a/lib/handlers/compile.interfaces.ts b/lib/handlers/compile.interfaces.ts
index 104450b44..af4204066 100644
--- a/lib/handlers/compile.interfaces.ts
+++ b/lib/handlers/compile.interfaces.ts
@@ -22,6 +22,8 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
+
// IF YOU MODIFY ANYTHING HERE PLEASE UPDATE THE DOCUMENTATION!
// This type models a request so all fields must be optional strings.
@@ -52,12 +54,12 @@ export type CompilationRequestArgs = {
export type CompileRequestJsonBody = {
options: CompilationRequestArgs;
source: string;
- bypassCache: boolean;
+ bypassCache: BypassCache;
};
export type CompileRequestTextBody = {
source: string;
- bypassCache: boolean;
+ bypassCache: BypassCache;
options: any;
userArguments: string;
executeParametersArgs: any;
diff --git a/lib/handlers/compile.ts b/lib/handlers/compile.ts
index ac19c7972..6ec2782f6 100644
--- a/lib/handlers/compile.ts
+++ b/lib/handlers/compile.ts
@@ -50,6 +50,7 @@ import {
} from './compile.interfaces.js';
import {remove} from '../common-utils.js';
import {CompilerOverrideOptions} from '../../types/compilation/compiler-overrides.interfaces.js';
+import {BypassCache, CompileChildLibraries, ExecutionParams} from '../../types/compilation/compilation.interfaces.js';
import {SentryCapture} from '../sentry.js';
temp.track();
@@ -82,20 +83,15 @@ function initialise(compilerEnv: CompilationEnvironment) {
}, tempDirCleanupSecs * 1000);
}
-export type ExecutionParams = {
- args: string[];
- stdin: string;
-};
-
type ParsedRequest = {
source: string;
options: string[];
backendOptions: Record<string, any>;
filters: ParseFiltersAndOutputOptions;
- bypassCache: boolean;
+ bypassCache: BypassCache;
tools: any;
executionParameters: ExecutionParams;
- libraries: any[];
+ libraries: CompileChildLibraries[];
};
export class CompileHandler {
@@ -353,7 +349,7 @@ export class CompileHandler {
options: string,
backendOptions: Record<string, any> = {},
filters: ParseFiltersAndOutputOptions,
- bypassCache = false,
+ bypassCache = BypassCache.None,
tools;
const execReqParams: ExecutionRequestParams = {};
let libraries: any[] = [];
@@ -363,7 +359,7 @@ export class CompileHandler {
const jsonRequest = this.checkRequestRequirements(req);
const requestOptions = jsonRequest.options;
source = jsonRequest.source;
- if (jsonRequest.bypassCache) bypassCache = true;
+ if (jsonRequest.bypassCache) bypassCache = jsonRequest.bypassCache;
options = requestOptions.userArguments;
const execParams = requestOptions.executeParameters || {};
execReqParams.args = execParams.args;
@@ -375,7 +371,7 @@ export class CompileHandler {
} else if (req.body && req.body.compiler) {
const textRequest = req.body as CompileRequestTextBody;
source = textRequest.source;
- if (textRequest.bypassCache) bypassCache = true;
+ if (textRequest.bypassCache) bypassCache = textRequest.bypassCache;
options = textRequest.userArguments;
execReqParams.args = textRequest.executeParametersArgs;
execReqParams.stdin = textRequest.executeParametersStdin;
@@ -423,6 +419,11 @@ export class CompileHandler {
for (const tool of tools) {
tool.args = utils.splitArguments(tool.args);
}
+
+ // Backwards compatibility: bypassCache used to be a boolean.
+ // Convert a boolean input to an enum's underlying numeric value
+ bypassCache = 1 * bypassCache;
+
return {
source,
options: utils.splitArguments(options),
@@ -497,7 +498,9 @@ export class CompileHandler {
this.cmakeCounter.inc({language: compiler.lang.id});
const options = this.parseRequest(req, compiler);
compiler
- .cmake(req.body.files, options)
+ // Backwards compatibility: bypassCache used to be a boolean.
+ // Convert a boolean input to an enum's underlying numeric value
+ .cmake(req.body.files, options, req.body.bypassCache * 1)
.then(result => {
if (result.didExecute || (result.execResult && result.execResult.didExecute))
this.cmakeExecuteCounter.inc({language: compiler.lang.id});
diff --git a/lib/llvm-ir.ts b/lib/llvm-ir.ts
index 5bdf7e651..4ddf9e58f 100644
--- a/lib/llvm-ir.ts
+++ b/lib/llvm-ir.ts
@@ -249,9 +249,9 @@ export class LlvmIrParser {
if (_.isString(ir)) {
return await this.processIr(ir, {
filterDebugInfo: !!filters.debugCalls,
- filterIRMetadata: filters.directives,
+ filterIRMetadata: !!filters.directives,
filterAttributes: false,
- demangle: filters.demangle,
+ demangle: !!filters.demangle,
// discard value names is handled earlier
});
}
diff --git a/static/compiler-service.ts b/static/compiler-service.ts
index 1fb435c43..89120dbc2 100644
--- a/static/compiler-service.ts
+++ b/static/compiler-service.ts
@@ -44,7 +44,7 @@ const ASCII_COLORS_RE = new RegExp(/\x1B\[[\d;]*m(.\[K)?/g);
export class CompilerService {
private readonly base = window.httpRoot;
private allowStoreCodeDebug: boolean;
- cache: LRUCache<string, CompilationResult>;
+ private cache: LRUCache<string, CompilationResult>;
private readonly compilersByLang: Record<string, Record<string, CompilerInfo>>;
constructor(eventHub: EventEmitter) {
@@ -214,7 +214,7 @@ export class CompilerService {
public async submit(request: Record<string, any>) {
request.allowStoreCodeDebug = this.allowStoreCodeDebug;
const jsonRequest = JSON.stringify(request);
- if (options.doCache) {
+ if (options.doCache && !request.bypassCache) {
const cachedResult = this.cache.get(jsonRequest);
if (cachedResult) {
return {
@@ -252,7 +252,7 @@ export class CompilerService {
public submitCMake(request: Record<string, any>) {
request.allowStoreCodeDebug = this.allowStoreCodeDebug;
const jsonRequest = JSON.stringify(request);
- if (options.doCache) {
+ if (options.doCache && !request.bypassCache) {
const cachedResult = this.cache.get(jsonRequest);
if (cachedResult) {
return Promise.resolve({
diff --git a/static/panes/compiler-request.interfaces.ts b/static/panes/compiler-request.interfaces.ts
index 9c931e678..69fb390a8 100644
--- a/static/panes/compiler-request.interfaces.ts
+++ b/static/panes/compiler-request.interfaces.ts
@@ -22,77 +22,9 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
-import type {LLVMOptPipelineBackendOptions} from '../../types/compilation/llvm-opt-pipeline-output.interfaces.js';
-import type {PPOptions} from './pp-view.interfaces.js';
-import type {GccDumpViewSelectedPass} from './gccdump-view.interfaces.js';
-import type {FiledataPair} from '../../types/compilation/compilation.interfaces.js';
-import type {ConfiguredOverrides} from '../compilation/compiler-overrides.interfaces.js';
-import {LLVMIrBackendOptions} from '../compilation/ir.interfaces.js';
-
-export type ActiveTools = {
- id: number;
- args: string[];
- stdin: string;
-};
-
-export type CompilationRequestOptions = {
- userArguments: string;
- compilerOptions: {
- executorRequest?: boolean;
- skipAsm?: boolean;
- producePp?: PPOptions | null;
- produceAst?: boolean;
- produceGccDump?: {
- opened: boolean;
- pass?: GccDumpViewSelectedPass;
- treeDump?: boolean;
- rtlDump?: boolean;
- ipaDump?: boolean;
- dumpFlags: any;
- };
- produceOptInfo?: boolean;
- produceCfg?: boolean;
- produceGnatDebugTree?: boolean;
- produceGnatDebug?: boolean;
- produceIr?: LLVMIrBackendOptions | null;
- produceLLVMOptPipeline?: LLVMOptPipelineBackendOptions | null;
- produceDevice?: boolean;
- produceRustMir?: boolean;
- produceRustMacroExp?: boolean;
- produceRustHir?: boolean;
- produceHaskellCore?: boolean;
- produceHaskellStg?: boolean;
- produceHaskellCmm?: boolean;
- cmakeArgs?: string;
- customOutputFilename?: string;
- overrides?: ConfiguredOverrides;
- };
- executeParameters: {
- args: string;
- stdin: string;
- };
- filters: Record<string, boolean>;
- tools: ActiveTools[];
- libraries: CompileChildLibraries[];
-};
-
-export type CompilationRequest = {
- source: string;
- compiler: string;
- options: CompilationRequestOptions;
- lang: string | null;
- files: FiledataPair[];
- bypassCache?: boolean;
-};
-
export type LangInfo = {
compiler: string;
options: string;
execArgs: string;
execStdin: string;
};
-
-export type CompileChildLibraries = {
- id: string;
- version: string;
-};
diff --git a/static/panes/compiler.ts b/static/panes/compiler.ts
index b785c54e6..accc8a280 100644
--- a/static/panes/compiler.ts
+++ b/static/panes/compiler.ts
@@ -57,7 +57,14 @@ import {PPOptions} from './pp-view.interfaces.js';
import {CompilationStatus} from '../compiler-service.interfaces.js';
import {WidgetState} from '../widgets/libs-widget.interfaces.js';
import {LLVMOptPipelineBackendOptions} from '../../types/compilation/llvm-opt-pipeline-output.interfaces.js';
-import {CompilationResult, FiledataPair} from '../../types/compilation/compilation.interfaces.js';
+import {
+ ActiveTools,
+ BypassCache,
+ CompilationRequest,
+ CompilationRequestOptions,
+ CompilationResult,
+ FiledataPair,
+} from '../../types/compilation/compilation.interfaces.js';
import {ResultLine} from '../../types/resultline/resultline.interfaces.js';
import * as utils from '../utils.js';
import {editor} from 'monaco-editor';
@@ -70,7 +77,6 @@ import {SourceAndFiles} from '../download-service.js';
import fileSaver = require('file-saver');
import {ICompilerShared} from '../compiler-shared.interfaces.js';
import {CompilerShared} from '../compiler-shared.js';
-import type {ActiveTools, CompilationRequest, CompilationRequestOptions} from './compiler-request.interfaces.js';
import {SentryCapture} from '../sentry.js';
import {LLVMIrBackendOptions} from '../compilation/ir.interfaces.js';
@@ -1241,7 +1247,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
options: options,
lang: this.currentLangId,
files: tree.multifileService.getFiles(),
- bypassCache: false,
+ bypassCache: BypassCache.None,
};
const fetches: Promise<void>[] = [];
@@ -1268,7 +1274,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
const cmakeProject = tree.multifileService.isACMakeProject();
request.files.push(...moreFiles);
- if (bypassCache) request.bypassCache = true;
+ if (bypassCache) request.bypassCache = BypassCache.Compilation;
if (!this.compiler) {
this.onCompileResponse(request, this.errorResult('<Please select a compiler>'), false);
} else if (cmakeProject && request.source === '') {
@@ -1293,9 +1299,9 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
options: options,
lang: this.currentLangId,
files: sourceAndFiles.files,
- bypassCache: false,
+ bypassCache: BypassCache.None,
};
- if (bypassCache) request.bypassCache = true;
+ if (bypassCache) request.bypassCache = BypassCache.Compilation;
if (!this.compiler) {
this.onCompileResponse(request, this.errorResult('<Please select a compiler>'), false);
} else {
@@ -2903,7 +2909,6 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
});
this.compileClearCache.on('click', () => {
- this.compilerService.cache.clear();
this.compile(true);
});
diff --git a/static/panes/device-view.ts b/static/panes/device-view.ts
index 40cbd759b..5d1cd7f06 100644
--- a/static/panes/device-view.ts
+++ b/static/panes/device-view.ts
@@ -42,7 +42,6 @@ import {AssemblyDocumentationInstructionSet} from '../../types/features/assembly
import {Alert} from '../widgets/alert';
import {Compiler} from './compiler';
-
export class DeviceAsm extends MonacoPane<monaco.editor.IStandaloneCodeEditor, DeviceAsmState> {
private decorations: Record<string, monaco.editor.IModelDeltaDecoration[]>;
private prevDecorations: string[];
diff --git a/static/panes/executor.ts b/static/panes/executor.ts
index b35ee9199..7f4170fd5 100644
--- a/static/panes/executor.ts
+++ b/static/panes/executor.ts
@@ -45,14 +45,20 @@ import {ExecutorState} from './executor.interfaces.js';
import {CompilerInfo} from '../../types/compiler.interfaces.js';
import {Language} from '../../types/languages.interfaces.js';
import {LanguageLibs} from '../options.interfaces.js';
-import {CompilationResult, FiledataPair} from '../../types/compilation/compilation.interfaces.js';
+import {
+ BypassCache,
+ CompilationRequest,
+ CompilationRequestOptions,
+ CompilationResult,
+ FiledataPair,
+} from '../../types/compilation/compilation.interfaces.js';
import {ResultLine} from '../../types/resultline/resultline.interfaces.js';
import {CompilationStatus as CompilerServiceCompilationStatus} from '../compiler-service.interfaces.js';
import {CompilerPicker} from '../widgets/compiler-picker.js';
import {SourceAndFiles} from '../download-service.js';
import {ICompilerShared} from '../compiler-shared.interfaces.js';
import {CompilerShared} from '../compiler-shared.js';
-import {CompilationRequest, CompilationRequestOptions, LangInfo} from './compiler-request.interfaces.js';
+import {LangInfo} from './compiler-request.interfaces.js';
const languages = options.languages;
@@ -93,7 +99,6 @@ export class Executor extends Pane<ExecutorState> {
private compilerPicker: CompilerPicker;
private currentLangId: string;
private toggleWrapButton: Toggles;
- private compileClearCache: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private outputContentRoot: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private executionStatusSection: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private compilerOutputSection: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
@@ -114,7 +119,8 @@ export class Executor extends Pane<ExecutorState> {
private panelArgs: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private panelStdin: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private wrapTitle: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
- private triggerCompilationButton: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
+ private rerunButton: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
+ private compileClearCache: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private wrapButton: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private toggleCompilation: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
private toggleArgs: JQuery<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>;
@@ -260,7 +266,7 @@ export class Executor extends Pane<ExecutorState> {
return {stdout: [], timedOut: false, code: -1, stderr: message};
}
- compile(bypassCache?: boolean): void {
+ compile(bypassCache?: BypassCache): void {
if (this.deferCompiles) {
this.needsCompile = true;
return;
@@ -297,7 +303,7 @@ export class Executor extends Pane<ExecutorState> {
}
}
- compileFromEditorSource(options: CompilationRequestOptions, bypassCache?: boolean): void {
+ compileFromEditorSource(options: CompilationRequestOptions, bypassCache?: BypassCache): void {
if (!this.compiler?.supportsExecute) {
this.alertSystem.notify('This compiler (' + this.compiler?.name + ') does not support execution', {
group: 'execution',
@@ -312,7 +318,7 @@ export class Executor extends Pane<ExecutorState> {
lang: this.currentLangId,
files: sourceAndFiles.files,
};
- if (bypassCache) request.bypassCache = true;
+ if (bypassCache) request.bypassCache = bypassCache;
if (!this.compiler) {
this.onCompileResponse(request, this.errorResult('<Please select a compiler>'), false);
} else {
@@ -321,7 +327,7 @@ export class Executor extends Pane<ExecutorState> {
});
}
- compileFromTree(options: CompilationRequestOptions, bypassCache?: boolean): void {
+ compileFromTree(options: CompilationRequestOptions, bypassCache?: BypassCache): void {
const tree = this.hub.getTreeById(this.sourceTreeId ?? -1);
if (!tree) {
this.sourceTreeId = null;
@@ -361,7 +367,7 @@ export class Executor extends Pane<ExecutorState> {
const treeState = tree.currentState();
const cmakeProject = tree.multifileService.isACMakeProject();
- if (bypassCache) request.bypassCache = true;
+ if (bypassCache) request.bypassCache = bypassCache;
if (!this.compiler) {
this.onCompileResponse(request, this.errorResult('<Please select a compiler>'), false);
} else if (cmakeProject && request.source === '') {
@@ -740,7 +746,6 @@ export class Executor extends Pane<ExecutorState> {
}
initButtons(state: PaneState & ExecutorState): void {
- this.compileClearCache = this.domRoot.find('.clear-cache');
this.outputContentRoot = this.domRoot.find('pre.content');
this.executionStatusSection = this.outputContentRoot.find('.execution-status');
this.compilerOutputSection = this.outputContentRoot.find('.compiler-output');
@@ -800,7 +805,8 @@ export class Executor extends Pane<ExecutorState> {
this.wrapButton = this.domRoot.find('.wrap-lines');
this.wrapTitle = this.wrapButton.prop('title');
- this.triggerCompilationButton = this.bottomBar.find('.trigger-compilation');
+ this.rerunButton = this.bottomBar.find('.rerun');
+ this.compileClearCache = this.bottomBar.find('.clear-cache');
this.initToggleButtons(state);
}
@@ -928,11 +934,6 @@ export class Executor extends Pane<ExecutorState> {
this.execStdinField.on('change', execStdinChange).on('keyup', execStdinChange);
- this.compileClearCache.on('click', () => {
- this.hub.compilerService.cache.clear();
- this.compile(true);
- });
-
// Dismiss the popover on escape.
$(document).on('keyup.editable', e => {
if (e.which === 27) {
@@ -956,8 +957,12 @@ export class Executor extends Pane<ExecutorState> {
this.togglePanel(this.toggleCompilerOut, this.compilerOutputSection);
});
- this.triggerCompilationButton.on('click', () => {
- this.compile(true);
+ this.rerunButton.on('click', () => {
+ this.compile(BypassCache.Execution);
+ });
+
+ this.compileClearCache.on('click', () => {
+ this.compile(BypassCache.Compilation);
});
// Dismiss on any click that isn't either in the opening element, inside
diff --git a/static/styles/explorer.scss b/static/styles/explorer.scss
index 834a53fa7..95429c0b9 100644
--- a/static/styles/explorer.scss
+++ b/static/styles/explorer.scss
@@ -442,11 +442,6 @@ pre.content.wrap * {
}
}
-.clear-cache {
- position: absolute;
- right: 0;
-}
-
.change-language {
line-height: 14px;
min-width: 200px !important;
diff --git a/static/styles/themes/dark-theme.scss b/static/styles/themes/dark-theme.scss
index cb2e74a85..0e4b95513 100644
--- a/static/styles/themes/dark-theme.scss
+++ b/static/styles/themes/dark-theme.scss
@@ -530,12 +530,12 @@ textarea.form-control {
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
60deg,
- #ED4242 0,
- #FFAA44 20%,
- #FFF344 40%,
- #43A35B 60%,
- #447CFF 80%,
- #9C44A9 100%
+ #ed4242 0,
+ #ffaa44 20%,
+ #fff344 40%,
+ #43a35b 60%,
+ #447cff 80%,
+ #9c44a9 100%
);
}
diff --git a/static/styles/themes/default-theme.scss b/static/styles/themes/default-theme.scss
index 7c20fa750..30c6ac59e 100644
--- a/static/styles/themes/default-theme.scss
+++ b/static/styles/themes/default-theme.scss
@@ -120,12 +120,12 @@ a.navbar-brand img.logo.normal {
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
60deg,
- #ED4242 0,
- #FFAA44 20%,
- #FFF344 40%,
- #43A35B 60%,
- #447CFF 80%,
- #9C44A9 100%
+ #ed4242 0,
+ #ffaa44 20%,
+ #fff344 40%,
+ #43a35b 60%,
+ #447cff 80%,
+ #9c44a9 100%
);
}
diff --git a/static/styles/themes/pink-theme.scss b/static/styles/themes/pink-theme.scss
index bf9907597..0d2bd512e 100644
--- a/static/styles/themes/pink-theme.scss
+++ b/static/styles/themes/pink-theme.scss
@@ -551,12 +551,12 @@ textarea.form-control {
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
60deg,
- #ED4242 0,
- #FFAA44 20%,
- #FFF344 40%,
- #43A35B 60%,
- #447CFF 80%,
- #9C44A9 100%
+ #ed4242 0,
+ #ffaa44 20%,
+ #fff344 40%,
+ #43a35b 60%,
+ #447cff 80%,
+ #9c44a9 100%
);
}
diff --git a/test/handlers/compile-tests.js b/test/handlers/compile-tests.js
index d7ddba99e..cbcc2a759 100644
--- a/test/handlers/compile-tests.js
+++ b/test/handlers/compile-tests.js
@@ -27,6 +27,7 @@ import express from 'express';
import {CompileHandler, SetTestMode} from '../../lib/handlers/compile.js';
import {fakeProps} from '../../lib/properties.js';
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
import {chai, makeCompilationEnvironment} from '../utils.js';
SetTestMode();
@@ -361,7 +362,7 @@ describe('Compiler tests', () => {
res.should.be.json;
res.body.input.options.should.deep.equals({
backendOptions: {},
- bypassCache: false,
+ bypassCache: BypassCache.None,
executionParameters: {
args: [],
stdin: '',
diff --git a/types/compilation/compilation.interfaces.ts b/types/compilation/compilation.interfaces.ts
index 994c12820..e79c20eb0 100644
--- a/types/compilation/compilation.interfaces.ts
+++ b/types/compilation/compilation.interfaces.ts
@@ -24,12 +24,97 @@
import {BuildEnvDownloadInfo} from '../../lib/buildenvsetup/buildenv.interfaces.js';
import {IAsmParser} from '../../lib/parsers/asm-parser.interfaces.js';
+import type {GccDumpViewSelectedPass} from '../../static/panes/gccdump-view.interfaces.js';
+import type {PPOptions} from '../../static/panes/pp-view.interfaces.js';
import {CompilerInfo} from '../compiler.interfaces.js';
import {BasicExecutionResult} from '../execution/execution.interfaces.js';
+import {ParseFiltersAndOutputOptions} from '../features/filters.interfaces.js';
import {ResultLine} from '../resultline/resultline.interfaces.js';
import {Artifact, ToolResult} from '../tool.interfaces.js';
-import {LLVMOptPipelineOutput} from './llvm-opt-pipeline-output.interfaces.js';
+import {ConfiguredOverrides} from './compiler-overrides.interfaces.js';
+import {LLVMIrBackendOptions} from './ir.interfaces.js';
+import {LLVMOptPipelineBackendOptions, LLVMOptPipelineOutput} from './llvm-opt-pipeline-output.interfaces.js';
+
+export type ActiveTools = {
+ id: number;
+ args: string[];
+ stdin: string;
+};
+
+export type ExecutionParams = {
+ args: string[] | string;
+ stdin: string;
+};
+
+export type CompileChildLibraries = {
+ id: string;
+ version: string;
+};
+
+export type CompilationRequestOptions = {
+ userArguments: string;
+ compilerOptions: {
+ executorRequest?: boolean;
+ skipAsm?: boolean;
+ producePp?: PPOptions | null;
+ produceAst?: boolean;
+ produceGccDump?: {
+ opened: boolean;
+ pass?: GccDumpViewSelectedPass;
+ treeDump?: boolean;
+ rtlDump?: boolean;
+ ipaDump?: boolean;
+ dumpFlags: any;
+ };
+ produceOptInfo?: boolean;
+ produceCfg?: boolean;
+ produceGnatDebugTree?: boolean;
+ produceGnatDebug?: boolean;
+ produceIr?: LLVMIrBackendOptions | null;
+ produceLLVMOptPipeline?: LLVMOptPipelineBackendOptions | null;
+ produceDevice?: boolean;
+ produceRustMir?: boolean;
+ produceRustMacroExp?: boolean;
+ produceRustHir?: boolean;
+ produceHaskellCore?: boolean;
+ produceHaskellStg?: boolean;
+ produceHaskellCmm?: boolean;
+ cmakeArgs?: string;
+ customOutputFilename?: string;
+ overrides?: ConfiguredOverrides;
+ };
+ executeParameters: ExecutionParams;
+ filters: ParseFiltersAndOutputOptions;
+ tools: ActiveTools[];
+ libraries: CompileChildLibraries[];
+};
+
+// Carefully chosen for backwards compatibility
+// Compilation will imply exec (this is important for backward compatibility, though there is a world in which it could
+// be desirable to only bypass a compilation cache and not the execution pass)
+export enum BypassCache {
+ None = 0,
+ Compilation = 1,
+ Execution = 2,
+}
+
+export function bypassCompilationCache(value: BypassCache) {
+ return value === BypassCache.Compilation;
+}
+
+export function bypassExecutionCache(value: BypassCache) {
+ return value === BypassCache.Compilation || value === BypassCache.Execution;
+}
+
+export type CompilationRequest = {
+ source: string;
+ compiler: string;
+ options: CompilationRequestOptions;
+ lang: string | null;
+ files: FiledataPair[];
+ bypassCache?: BypassCache;
+};
export type CompilationResult = {
code: number;
diff --git a/types/compiler.interfaces.ts b/types/compiler.interfaces.ts
index 9036e0ce9..e641f3529 100644
--- a/types/compiler.interfaces.ts
+++ b/types/compiler.interfaces.ts
@@ -22,6 +22,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {BypassCache} from './compilation/compilation.interfaces.js';
import {AllCompilerOverrideOptions} from './compilation/compiler-overrides.interfaces.js';
import {ICompilerArguments} from './compiler-arguments.interfaces.js';
import {Language, LanguageKey} from './languages.interfaces.js';
@@ -143,7 +144,7 @@ export interface ICompiler {
possibleArguments: ICompilerArguments;
lang: Language;
compile(source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries, files);
- cmake(files, key);
+ cmake(files, key, bypassCache: BypassCache);
initialise(mtime: Date, clientOptions, isPrediscovered: boolean);
getInfo(): CompilerInfo;
}
diff --git a/types/features/filters.interfaces.ts b/types/features/filters.interfaces.ts
index 5323cb248..13179c544 100644
--- a/types/features/filters.interfaces.ts
+++ b/types/features/filters.interfaces.ts
@@ -27,24 +27,26 @@
// options" and "Compiler output filters" drop down menu in a compiler pane.
// TODO(jeremy-rifkin): Change name to include "filters"?
-export type CompilerOutputOptions = {
+export type CompilerOutputOptions = Partial<{
binary: boolean;
binaryObject: boolean;
execute: boolean;
demangle: boolean;
intel: boolean;
-};
+}>;
export type preProcessLinesFunc = (lines: string[]) => string[];
-export type ParseFiltersAndOutputOptions = {
- labels: boolean;
- libraryCode: boolean;
- directives: boolean;
- commentOnly: boolean;
- trim: boolean;
- debugCalls?: boolean;
- dontMaskFilenames?: boolean;
- optOutput: boolean;
- preProcessLines?: preProcessLinesFunc;
- preProcessBinaryAsmLines?: preProcessLinesFunc;
-} & CompilerOutputOptions;
+export type ParseFiltersAndOutputOptions = Partial<
+ {
+ labels: boolean;
+ libraryCode: boolean;
+ directives: boolean;
+ commentOnly: boolean;
+ trim: boolean;
+ debugCalls?: boolean;
+ dontMaskFilenames?: boolean;
+ optOutput: boolean;
+ preProcessLines?: preProcessLinesFunc;
+ preProcessBinaryAsmLines?: preProcessLinesFunc;
+ } & CompilerOutputOptions
+>;
diff --git a/views/templates/panes/executor.pug b/views/templates/panes/executor.pug
index 7abb7b582..b18b76307 100644
--- a/views/templates/panes/executor.pug
+++ b/views/templates/panes/executor.pug
@@ -24,8 +24,6 @@
button.btn.btn-sm.btn-light.toggle-compilerout.active(title="Compiler output" aria-label="Toggle showing compiler output")
span.fas.fa-sign-out-alt
span.hideable Compiler output
- button.btn.btn-sm.btn-light.clear-cache(title="Clear cache & recompile")
- span.fas.fa-redo
.top-bar.btn-toolbar.bg-light.panel-compilation(role="toolbar")
.btn-group.btn-group-sm(role="group" aria-label="Compiler picker")
.input-group
@@ -58,7 +56,9 @@
.compiler-output
.execution-output
.bottom-bar.bg-light
- button.btn.btn-sm.btn-light.trigger-compilation(title="Trigger compilation")
+ button.btn.btn-sm.btn-light.rerun(title="Rerun")
+ span.fas.fa-circle-play
+ button.btn.btn-sm.btn-light.clear-cache(title="Clear cache & recompile")
span.fas.fa-redo
span.short-compiler-name
button.btn.btn-sm.btn-light.fas.fa-info.full-compiler-name(data-trigger="click" style="cursor: pointer;" role="button")