aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com>2023-06-17 19:41:26 -0400
committerGitHub <noreply@github.com>2023-06-17 19:41:26 -0400
commit42ea9cc128ced1061f7f15c003d9c6b271367b2b (patch)
tree557ee99f4cc6c3ad708f6f1cdbcfd9666903d09f
parentda064506f30038f4df217bdccccf90d089f0d591 (diff)
downloadcompiler-explorer-gh-7811.tar.gz
compiler-explorer-gh-7811.zip
General work on solidifying the instruction set system (#5156)gh-7811
Mainly type work
-rw-r--r--etc/scripts/docenizers/docenizer-arm.py4
-rw-r--r--lib/assert.ts16
-rw-r--r--lib/cfg/cfg.ts2
-rw-r--r--lib/compiler-finder.ts10
-rw-r--r--lib/global.ts33
-rw-r--r--lib/instructionsets.ts68
-rw-r--r--static/panes/compiler.ts18
-rw-r--r--static/panes/device-view.ts6
-rw-r--r--types/compiler.interfaces.ts3
-rw-r--r--types/features/assembly-documentation.interfaces.ts16
-rw-r--r--types/instructionsets.ts61
11 files changed, 190 insertions, 47 deletions
diff --git a/etc/scripts/docenizers/docenizer-arm.py b/etc/scripts/docenizers/docenizer-arm.py
index cee8e1b51..dbf9c8a24 100644
--- a/etc/scripts/docenizers/docenizer-arm.py
+++ b/etc/scripts/docenizers/docenizer-arm.py
@@ -32,7 +32,7 @@ STRIP_SUFFIX = re.compile(r'\s*(\(.*\))?\s*(--.*)?')
FLDMX_RE = re.compile(r'^(FLDM)(\*)(X)')
FLDMX_SET = set(['DB', 'IA'])
-#arm64
+#aarch64
CONDITION_RE = re.compile(r'^([A-Z][A-Z0-9]*\.?)(cond|<cc>)()')
CONDITION_SET = set(['EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC', 'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'AL'])
FRINT_RE = re.compile(r'^(FRINT)(<r>)()')
@@ -184,7 +184,7 @@ def docenizer():
print("Called with: {}".format(args))
with open(args.configfile) as f:
- config = Config(**json.load(f))
+ config = Config(**json.load(f))
print("Use configs: {}".format(json.dumps(config, default=lambda o: o.__dict__)))
# If we don't have the html folder already...
if not os.path.isdir(os.path.join(args.inputfolder, config.archive.subdir)):
diff --git a/lib/assert.ts b/lib/assert.ts
index 204d0c8da..658034bb7 100644
--- a/lib/assert.ts
+++ b/lib/assert.ts
@@ -28,9 +28,19 @@ import path from 'path';
import {parse} from './stacktrace.js';
import {isString} from './common-utils.js';
-function check_path(parent: string, directory: string) {
+const filePrefix = 'file://';
+
+function removeFileProtocol(path: string) {
+ if (path.startsWith(filePrefix)) {
+ return path.slice(filePrefix.length);
+ } else {
+ return path;
+ }
+}
+
+function check_path(parent: URL, directory: string) {
// https://stackoverflow.com/a/45242825/15675011
- const relative = path.relative(parent, directory);
+ const relative = path.relative(parent.pathname, directory);
if (relative && !relative.startsWith('..') && !path.isAbsolute(relative)) {
return relative;
} else {
@@ -45,7 +55,7 @@ function get_diagnostic() {
const invoker_frame = trace[3];
if (invoker_frame.fileName && invoker_frame.lineNumber) {
// Just out of an abundance of caution...
- const relative = check_path(global.ce_base_directory, invoker_frame.fileName);
+ const relative = check_path(global.ce_base_directory, removeFileProtocol(invoker_frame.fileName));
if (relative) {
try {
const file = fs.readFileSync(invoker_frame.fileName, 'utf8');
diff --git a/lib/cfg/cfg.ts b/lib/cfg/cfg.ts
index 4053e1235..b74140f04 100644
--- a/lib/cfg/cfg.ts
+++ b/lib/cfg/cfg.ts
@@ -54,7 +54,7 @@ export function generateStructure(compilerInfo: CompilerInfo, asmArr: ResultLine
// figure out what we're working with
const isa = isLlvmIr ? 'llvmir' : compilerInfo.instructionSet;
const compilerGroup = isLlvmIr ? 'llvmir' : isLLVMBased(compilerInfo) ? 'clang' : compilerInfo.group;
- const instructionSet = new (getInstructionSetByKey(isa))();
+ const instructionSet = new (getInstructionSetByKey(isa ?? 'base'))();
const parser = new (getParserByKey(compilerGroup))(instructionSet);
const code = parser.filterData(asmArr);
diff --git a/lib/compiler-finder.ts b/lib/compiler-finder.ts
index d7deec7c8..6a4a1b134 100644
--- a/lib/compiler-finder.ts
+++ b/lib/compiler-finder.ts
@@ -34,7 +34,7 @@ import urljoin from 'url-join';
import type {CompilerInfo, PreliminaryCompilerInfo} from '../types/compiler.interfaces.js';
import type {Language, LanguageKey} from '../types/languages.interfaces.js';
-import {unwrap} from './assert.js';
+import {unwrap, assert} from './assert.js';
import {InstanceFetcher} from './aws.js';
import {CompileHandler} from './handlers/compile.js';
import {logger} from './logger.js';
@@ -43,6 +43,7 @@ import {CompilerProps} from './properties.js';
import type {PropertyGetter} from './properties.interfaces.js';
import {basic_comparator, remove} from './common-utils.js';
import {getPossibleGccToolchainsFromCompilerInfo} from './toolchain-utils.js';
+import {InstructionSet, InstructionSetsList} from '../types/instructionsets.js';
const sleep = promisify(setTimeout);
@@ -258,6 +259,11 @@ export class CompilerFinder {
})();
const exe = props('exe', compilerId);
const exePath = path.dirname(exe);
+ const instructionSet = props<string | number>('instructionSet', '').toString() as InstructionSet | '';
+ assert(
+ instructionSet === '' || InstructionSetsList.includes(instructionSet),
+ `Unexpected instruction set ${instructionSet} ${compilerId}`,
+ );
const compilerInfo: PreliminaryCompilerInfo = {
id: compilerId,
exe: exe,
@@ -281,7 +287,7 @@ export class CompilerFinder {
objdumperArgs: splitArrayPropsOrEmpty('objdumperArgs', '|'),
intelAsm: props('intelAsm', ''),
supportsAsmDocs: props('supportsAsmDocs', true),
- instructionSet: props<string | number>('instructionSet', '').toString(),
+ instructionSet: instructionSet === '' ? null : instructionSet,
needsMulti: !!props('needsMulti', true),
adarts: props('adarts', ''),
supportsDemangle: !!demangler,
diff --git a/lib/global.ts b/lib/global.ts
new file mode 100644
index 000000000..9ab786f66
--- /dev/null
+++ b/lib/global.ts
@@ -0,0 +1,33 @@
+// 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.
+
+declare global {
+ // var is required
+ // eslint-disable-next-line no-var
+ var ce_base_directory: URL;
+}
+
+// Necessary because we're not exporting any actual symbols from this file
+// See https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html
+export {};
diff --git a/lib/instructionsets.ts b/lib/instructionsets.ts
index 1b101b66a..4471d01be 100644
--- a/lib/instructionsets.ts
+++ b/lib/instructionsets.ts
@@ -22,14 +22,16 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {InstructionSet} from '../types/instructionsets.js';
+
type InstructionSetMethod = {
target: string[];
path: string[];
};
export class InstructionSets {
- private defaultInstructionset = 'amd64';
- private supported: Record<string, InstructionSetMethod> = {};
+ private defaultInstructionset: InstructionSet = 'amd64';
+ private supported: Record<InstructionSet, InstructionSetMethod>;
constructor() {
this.supported = {
@@ -85,7 +87,7 @@ export class InstructionSets {
target: ['rv32'],
path: ['/riscv32-'],
},
- sh : {
+ sh: {
target: ['sh'],
path: ['/sh-'],
},
@@ -109,7 +111,7 @@ export class InstructionSets {
target: ['wasm64'],
path: [],
},
- xstensa: {
+ xtensa: {
target: ['xtensa'],
path: ['/xtensa-'],
},
@@ -121,14 +123,60 @@ export class InstructionSets {
target: [],
path: [],
},
+ java: {
+ target: [],
+ path: [],
+ },
+ llvm: {
+ target: [],
+ path: [],
+ },
+ python: {
+ target: [],
+ path: [],
+ },
+ ptx: {
+ target: [],
+ path: [],
+ },
+ amd64: {
+ target: [],
+ path: [],
+ },
+ evm: {
+ target: [],
+ path: [],
+ },
+ mos6502: {
+ target: [],
+ path: [],
+ },
+ sass: {
+ target: [],
+ path: [],
+ },
+ beam: {
+ target: [],
+ path: [],
+ },
+ hook: {
+ target: [],
+ path: [],
+ },
+ spirv: {
+ target: [],
+ path: [],
+ },
};
}
- async getCompilerInstructionSetHint(compilerArch: string | boolean, exe: string): Promise<string> {
+ async getCompilerInstructionSetHint(compilerArch: string | boolean, exe: string): Promise<InstructionSet> {
return new Promise(resolve => {
if (compilerArch && typeof compilerArch === 'string') {
- for (const instructionSet in this.supported) {
- const method = this.supported[instructionSet];
+ for (const [instructionSet, method] of Object.entries(this.supported) as [
+ InstructionSet,
+ InstructionSetMethod,
+ ][]) {
for (const target of method.target) {
if (compilerArch.includes(target)) {
resolve(instructionSet);
@@ -137,8 +185,10 @@ export class InstructionSets {
}
}
} else {
- for (const instructionSet in this.supported) {
- const method = this.supported[instructionSet];
+ for (const [instructionSet, method] of Object.entries(this.supported) as [
+ InstructionSet,
+ InstructionSetMethod,
+ ][]) {
for (const path of method.path) {
if (exe.includes(path)) {
resolve(instructionSet);
diff --git a/static/panes/compiler.ts b/static/panes/compiler.ts
index 2b4002a7c..d990cf613 100644
--- a/static/panes/compiler.ts
+++ b/static/panes/compiler.ts
@@ -72,13 +72,13 @@ import IEditorMouseEvent = editor.IEditorMouseEvent;
import {Tool, ArtifactType, Artifact} from '../../types/tool.interfaces.js';
import {assert, unwrap, unwrapString} from '../assert.js';
import {CompilerOutputOptions} from '../../types/features/filters.interfaces.js';
-import {AssemblyDocumentationInstructionSet} from '../../types/features/assembly-documentation.interfaces.js';
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 {SentryCapture} from '../sentry.js';
import {LLVMIrBackendOptions} from '../compilation/ir.interfaces.js';
+import {InstructionSet} from '../instructionsets.js';
const toolIcons = require.context('../../views/resources/logos', false, /\.(png|svg)$/);
@@ -3420,8 +3420,8 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
view.setBigUint64(0, BigInt(numericValue.toString()), true);
if (numericValue.bitLength().lesserOrEquals(32))
result += ' = ' + view.getFloat32(0, true).toPrecision(9) + 'f';
- else // only subnormal doubles and zero may have upper 32 bits all 0, assume unlikely to be double
- result += ' = ' + view.getFloat64(0, true).toPrecision(17);
+ // only subnormal doubles and zero may have upper 32 bits all 0, assume unlikely to be double
+ else result += ' = ' + view.getFloat64(0, true).toPrecision(17);
// Printable ASCII character.
if (numericValue.greaterOrEquals(0x20) && numericValue.lesserOrEquals(0x7e)) {
@@ -3434,7 +3434,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
public static async getAsmInfo(
opcode: string,
- instructionSet: AssemblyDocumentationInstructionSet,
+ instructionSet: InstructionSet,
): Promise<AssemblyInstructionInfo | undefined> {
const cacheName = `asm/${instructionSet}/${opcode}`;
const cached = OpcodeCache.get(cacheName);
@@ -3552,10 +3552,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
this.isWordAsmKeyword(e.target.position.lineNumber, currentWord)
) {
try {
- const response = await Compiler.getAsmInfo(
- currentWord.word,
- this.compiler.instructionSet as AssemblyDocumentationInstructionSet,
- );
+ const response = await Compiler.getAsmInfo(currentWord.word, unwrap(this.compiler.instructionSet));
if (!response) return;
this.decorations.asmToolTip = [
{
@@ -3631,10 +3628,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
try {
if (this.compiler?.supportsAsmDocs) {
- const asmHelp = await Compiler.getAsmInfo(
- word.word,
- this.compiler.instructionSet as AssemblyDocumentationInstructionSet,
- );
+ const asmHelp = await Compiler.getAsmInfo(word.word, unwrap(this.compiler.instructionSet));
if (asmHelp) {
this.alertSystem.alert(opcode + ' help', asmHelp.html + appendInfo(asmHelp.url), {
onClose: () => {
diff --git a/static/panes/device-view.ts b/static/panes/device-view.ts
index 5d1cd7f06..0f271bd98 100644
--- a/static/panes/device-view.ts
+++ b/static/panes/device-view.ts
@@ -38,9 +38,9 @@ import {CompilerInfo} from '../../types/compiler.interfaces.js';
import {CompilationResult} from '../../types/compilation/compilation.interfaces.js';
import {ResultLine} from '../../types/resultline/resultline.interfaces.js';
import {assert} from '../assert.js';
-import {AssemblyDocumentationInstructionSet} from '../../types/features/assembly-documentation.interfaces';
import {Alert} from '../widgets/alert';
import {Compiler} from './compiler';
+import {InstructionSet} from '../instructionsets.js';
export class DeviceAsm extends MonacoPane<monaco.editor.IStandaloneCodeEditor, DeviceAsmState> {
private decorations: Record<string, monaco.editor.IModelDeltaDecoration[]>;
@@ -172,7 +172,7 @@ export class DeviceAsm extends MonacoPane<monaco.editor.IStandaloneCodeEditor, D
try {
const asmHelp = await Compiler.getAsmInfo(
word.word,
- this.selectedDevice.split(' ')[0].toLowerCase() as AssemblyDocumentationInstructionSet,
+ this.selectedDevice.split(' ')[0].toLowerCase() as InstructionSet,
);
if (asmHelp) {
this.alertSystem.alert(opcode + ' help', asmHelp.html + appendInfo(asmHelp.url), {
@@ -435,7 +435,7 @@ export class DeviceAsm extends MonacoPane<monaco.editor.IStandaloneCodeEditor, D
try {
const response = await Compiler.getAsmInfo(
currentWord.word,
- this.selectedDevice.split(' ')[0].toLowerCase() as AssemblyDocumentationInstructionSet,
+ this.selectedDevice.split(' ')[0].toLowerCase() as InstructionSet,
);
if (!response) return;
this.decorations.asmToolTip = [
diff --git a/types/compiler.interfaces.ts b/types/compiler.interfaces.ts
index e641f3529..30f4b272d 100644
--- a/types/compiler.interfaces.ts
+++ b/types/compiler.interfaces.ts
@@ -25,6 +25,7 @@
import {BypassCache} from './compilation/compilation.interfaces.js';
import {AllCompilerOverrideOptions} from './compilation/compiler-overrides.interfaces.js';
import {ICompilerArguments} from './compiler-arguments.interfaces.js';
+import {InstructionSet} from './instructionsets.js';
import {Language, LanguageKey} from './languages.interfaces.js';
import {Library} from './libraries/libraries.interfaces.js';
import {Tool, ToolInfo} from './tool.interfaces.js';
@@ -54,7 +55,7 @@ export type CompilerInfo = {
objdumperArgs: string[];
intelAsm: string;
supportsAsmDocs: boolean;
- instructionSet: string;
+ instructionSet: InstructionSet | null;
needsMulti: boolean;
adarts: string;
supportsDeviceAsmView?: boolean;
diff --git a/types/features/assembly-documentation.interfaces.ts b/types/features/assembly-documentation.interfaces.ts
index 1f46d1dad..fce10a592 100644
--- a/types/features/assembly-documentation.interfaces.ts
+++ b/types/features/assembly-documentation.interfaces.ts
@@ -23,23 +23,11 @@
// POSSIBILITY OF SUCH DAMAGE.
import {AssemblyInstructionInfo} from '../../lib/asm-docs/base.js';
-
-export type AssemblyDocumentationInstructionSet =
- | 'amd64'
- | 'arm32'
- | 'arm64'
- | 'avr'
- | 'evm'
- | 'java'
- | 'llvm'
- | 'mos6502'
- | 'ptx'
- | 'python'
- | 'sass';
+import {InstructionSet} from '../instructionsets.js';
export interface AssemblyDocumentationRequest {
/** Specifies which instruction set to look for */
- instructionSet: AssemblyDocumentationInstructionSet;
+ instructionSet: InstructionSet;
/** Instruction set opcode to look for */
opcode: string;
}
diff --git a/types/instructionsets.ts b/types/instructionsets.ts
new file mode 100644
index 000000000..95ee773c0
--- /dev/null
+++ b/types/instructionsets.ts
@@ -0,0 +1,61 @@
+// 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 const InstructionSetsList = [
+ '6502',
+ 'aarch64',
+ 'amd64',
+ 'arm32',
+ 'avr',
+ 'beam',
+ 'c6x',
+ 'ebpf',
+ 'evm',
+ 'hook',
+ 'java',
+ 'kvx',
+ 'llvm',
+ 'loongarch',
+ 'mips',
+ 'mos6502',
+ 'mrisc32',
+ 'msp430',
+ 'powerpc',
+ 'ptx',
+ 'python',
+ 'riscv32',
+ 'riscv64',
+ 's390x',
+ 'sass',
+ 'sh',
+ 'sparc',
+ 'spirv',
+ 'vax',
+ 'wasm32',
+ 'wasm64',
+ 'xtensa',
+ 'z80',
+] as const;
+
+export type InstructionSet = (typeof InstructionSetsList)[number];