blob: 0459193815af0f05db8b793b35555c6a1bb182df [file] [log] [blame] [raw]
Patrick Quist3f6004b2022-08-25 22:44:48 +02001// Copyright (c) 2022, Compiler Explorer Authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright
10// notice, this list of conditions and the following disclaimer in the
11// documentation and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23// POSSIBILITY OF SUCH DAMAGE.
24
25import path from 'path';
26
Patrick Quist64ce9392022-09-23 17:21:45 +020027import fs from 'fs-extra';
28
Patrick Quist3f6004b2022-08-25 22:44:48 +020029import {ExecutionOptions} from '../../types/compilation/compilation.interfaces';
Jeremy Rifkin6a6efae2023-01-29 13:22:30 -050030import {CompilerInfo} from '../../types/compiler.interfaces';
Marc Poulhiès2fa2bbb2022-11-28 21:37:15 +010031import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces';
Patrick Quist092ce122023-01-11 21:07:38 +010032import {ArtifactType} from '../../types/tool.interfaces';
Patrick Quist3f6004b2022-08-25 22:44:48 +020033import {BaseCompiler} from '../base-compiler';
34import {logger} from '../logger';
35import {AsmParserZ88dk} from '../parsers/asm-parser-z88dk';
36import * as utils from '../utils';
37
38export class z88dkCompiler extends BaseCompiler {
39 static get key() {
40 return 'z88dk';
41 }
42
Jeremy Rifkin6a6efae2023-01-29 13:22:30 -050043 constructor(compilerInfo: CompilerInfo, env) {
Patrick Quist3f6004b2022-08-25 22:44:48 +020044 super(compilerInfo, env);
45 this.outputFilebase = 'example';
46 this.asm = new AsmParserZ88dk(this.compilerProps);
47 }
48
49 public override getOutputFilename(dirPath: string, outputFilebase: string, key?: any): string {
50 let filename;
51 if (key && key.backendOptions && key.backendOptions.customOutputFilename) {
52 filename = key.backendOptions.customOutputFilename;
53 } else if (key && key.filters.binary) {
54 filename = `${outputFilebase}`;
55 } else {
56 filename = `${outputFilebase}.c.asm`;
57 }
58
59 if (dirPath) {
60 return path.join(dirPath, filename);
61 } else {
62 return filename;
63 }
64 }
65
66 public override orderArguments(
Jeremy Rifkin6a6efae2023-01-29 13:22:30 -050067 options: string[],
68 inputFilename: string,
69 libIncludes: string[],
70 libOptions: string[],
71 libPaths: string[],
72 libLinks: string[],
73 userOptions: string[],
74 staticLibLinks: string[],
Patrick Quist3f6004b2022-08-25 22:44:48 +020075 ) {
76 return userOptions.concat(
77 options,
78 [this.filename(inputFilename)],
79 libIncludes,
80 libOptions,
81 libPaths,
82 libLinks,
83 staticLibLinks,
84 );
85 }
86
Marc Poulhiès2fa2bbb2022-11-28 21:37:15 +010087 protected override optionsForFilter(filters: ParseFiltersAndOutputOptions, outputFilename: string): string[] {
Matt Godbolt749319f2022-12-28 11:42:14 -060088 if (filters.binary) {
Patrick Quist54c9cfd2022-08-25 23:31:37 +020089 return ['-o', outputFilename + '.s', '-create-app'];
Matt Godbolt749319f2022-12-28 11:42:14 -060090 } else {
91 return ['-S'];
Patrick Quist3f6004b2022-08-25 22:44:48 +020092 }
93 }
94
95 override getDefaultExecOptions(): ExecutionOptions {
96 const opts = super.getDefaultExecOptions();
97 opts.env.ZCCCFG = path.join(path.dirname(this.compiler.exe), '../share/z88dk/lib/config');
98 opts.env.PATH = process.env.PATH + path.delimiter + path.dirname(this.compiler.exe);
99
100 return opts;
101 }
102
Jeremy Rifkin6a6efae2023-01-29 13:22:30 -0500103 override getObjdumpOutputFilename(defaultOutputFilename: string) {
Patrick Quist54c9cfd2022-08-25 23:31:37 +0200104 return defaultOutputFilename;
Patrick Quist3f6004b2022-08-25 22:44:48 +0200105 }
106
Patrick Quist64ce9392022-09-23 17:21:45 +0200107 getTapefilename() {
108 return `${this.outputFilebase}.tap`;
109 }
110
Patrick Quist997a2d32022-09-25 23:02:13 +0200111 getSmsfilename() {
112 return `${this.outputFilebase}.sms`;
113 }
114
Marc Poulhiès2fa2bbb2022-11-28 21:37:15 +0100115 override async objdump(
116 outputFilename,
117 result: any,
118 maxSize: number,
119 intelAsm,
120 demangle,
Jeremy Rifkin6a6efae2023-01-29 13:22:30 -0500121 staticReloc: boolean,
122 dynamicReloc: boolean,
Marc Poulhiès2fa2bbb2022-11-28 21:37:15 +0100123 filters: ParseFiltersAndOutputOptions,
124 ) {
Patrick Quist3f6004b2022-08-25 22:44:48 +0200125 outputFilename = this.getObjdumpOutputFilename(outputFilename);
126
Patrick Quist54c9cfd2022-08-25 23:31:37 +0200127 // sometimes (with +z80 for example) the .bin file is written and the .s file is empty
Matt Godbolt749319f2022-12-28 11:42:14 -0600128 if (await utils.fileExists(outputFilename + '.bin')) {
129 outputFilename += '.bin';
130 } else {
131 if (await utils.fileExists(outputFilename + '.s')) {
132 outputFilename += '.s';
133 } else {
Patrick Quist54c9cfd2022-08-25 23:31:37 +0200134 result.asm = '<No output file ' + outputFilename + '.s>';
135 return result;
Patrick Quist54c9cfd2022-08-25 23:31:37 +0200136 }
Patrick Quist3f6004b2022-08-25 22:44:48 +0200137 }
138
139 const args = [outputFilename];
140
141 if (this.externalparser) {
142 const objResult = await this.externalparser.objdumpAndParseAssembly(result.dirPath, args, filters);
143 if (objResult.parsingTime !== undefined) {
144 objResult.objdumpTime = parseInt(result.execTime) - parseInt(result.parsingTime);
145 delete objResult.execTime;
146 }
147
148 result = {...result, ...objResult};
149 } else {
150 const execOptions: ExecutionOptions = {
151 maxOutput: maxSize,
152 customCwd: (result.dirPath as string) || path.dirname(outputFilename),
153 };
154 const objResult = await this.exec(this.compiler.objdumper, args, execOptions);
155
Matt Godbolt749319f2022-12-28 11:42:14 -0600156 if (objResult.code === 0) {
Patrick Quist3f6004b2022-08-25 22:44:48 +0200157 result.objdumpTime = objResult.execTime;
158 result.asm = this.postProcessObjdumpOutput(objResult.stdout);
Matt Godbolt749319f2022-12-28 11:42:14 -0600159 } else {
160 logger.error(`Error executing objdump ${this.compiler.objdumper}`, objResult);
161 result.asm = `<No output: objdump returned ${objResult.code}>`;
Patrick Quist3f6004b2022-08-25 22:44:48 +0200162 }
163 }
164
Patrick Quist64ce9392022-09-23 17:21:45 +0200165 if (result.code === 0 && filters.binary) {
166 const tapeFilepath = path.join(result.dirPath, this.getTapefilename());
partouf66e2ecf2022-09-23 19:00:09 +0200167 if (await utils.fileExists(tapeFilepath)) {
Patrick Quist092ce122023-01-11 21:07:38 +0100168 await this.addArtifactToResult(result, tapeFilepath, ArtifactType.zxtape);
partouf82deb602022-09-23 17:45:41 +0200169 }
Patrick Quist997a2d32022-09-25 23:02:13 +0200170
171 const smsFilepath = path.join(result.dirPath, this.getSmsfilename());
172 if (await utils.fileExists(smsFilepath)) {
Patrick Quist092ce122023-01-11 21:07:38 +0100173 await this.addArtifactToResult(result, smsFilepath, ArtifactType.smsrom);
Patrick Quist997a2d32022-09-25 23:02:13 +0200174 }
Patrick Quist64ce9392022-09-23 17:21:45 +0200175 }
176
Patrick Quist3f6004b2022-08-25 22:44:48 +0200177 return result;
178 }
179}