Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 1 | // 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 | |
| 25 | import path from 'path'; |
| 26 | |
Patrick Quist | 64ce939 | 2022-09-23 17:21:45 +0200 | [diff] [blame] | 27 | import fs from 'fs-extra'; |
| 28 | |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 29 | import {ExecutionOptions} from '../../types/compilation/compilation.interfaces'; |
Jeremy Rifkin | 6a6efae | 2023-01-29 13:22:30 -0500 | [diff] [blame] | 30 | import {CompilerInfo} from '../../types/compiler.interfaces'; |
Marc Poulhiès | 2fa2bbb | 2022-11-28 21:37:15 +0100 | [diff] [blame] | 31 | import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces'; |
Patrick Quist | 092ce12 | 2023-01-11 21:07:38 +0100 | [diff] [blame] | 32 | import {ArtifactType} from '../../types/tool.interfaces'; |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 33 | import {BaseCompiler} from '../base-compiler'; |
| 34 | import {logger} from '../logger'; |
| 35 | import {AsmParserZ88dk} from '../parsers/asm-parser-z88dk'; |
| 36 | import * as utils from '../utils'; |
| 37 | |
| 38 | export class z88dkCompiler extends BaseCompiler { |
| 39 | static get key() { |
| 40 | return 'z88dk'; |
| 41 | } |
| 42 | |
Jeremy Rifkin | 6a6efae | 2023-01-29 13:22:30 -0500 | [diff] [blame] | 43 | constructor(compilerInfo: CompilerInfo, env) { |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 44 | 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 Rifkin | 6a6efae | 2023-01-29 13:22:30 -0500 | [diff] [blame] | 67 | options: string[], |
| 68 | inputFilename: string, |
| 69 | libIncludes: string[], |
| 70 | libOptions: string[], |
| 71 | libPaths: string[], |
| 72 | libLinks: string[], |
| 73 | userOptions: string[], |
| 74 | staticLibLinks: string[], |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 75 | ) { |
| 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ès | 2fa2bbb | 2022-11-28 21:37:15 +0100 | [diff] [blame] | 87 | protected override optionsForFilter(filters: ParseFiltersAndOutputOptions, outputFilename: string): string[] { |
Matt Godbolt | 749319f | 2022-12-28 11:42:14 -0600 | [diff] [blame] | 88 | if (filters.binary) { |
Patrick Quist | 54c9cfd | 2022-08-25 23:31:37 +0200 | [diff] [blame] | 89 | return ['-o', outputFilename + '.s', '-create-app']; |
Matt Godbolt | 749319f | 2022-12-28 11:42:14 -0600 | [diff] [blame] | 90 | } else { |
| 91 | return ['-S']; |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 92 | } |
| 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 Rifkin | 6a6efae | 2023-01-29 13:22:30 -0500 | [diff] [blame] | 103 | override getObjdumpOutputFilename(defaultOutputFilename: string) { |
Patrick Quist | 54c9cfd | 2022-08-25 23:31:37 +0200 | [diff] [blame] | 104 | return defaultOutputFilename; |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 105 | } |
| 106 | |
Patrick Quist | 64ce939 | 2022-09-23 17:21:45 +0200 | [diff] [blame] | 107 | getTapefilename() { |
| 108 | return `${this.outputFilebase}.tap`; |
| 109 | } |
| 110 | |
Patrick Quist | 997a2d3 | 2022-09-25 23:02:13 +0200 | [diff] [blame] | 111 | getSmsfilename() { |
| 112 | return `${this.outputFilebase}.sms`; |
| 113 | } |
| 114 | |
Marc Poulhiès | 2fa2bbb | 2022-11-28 21:37:15 +0100 | [diff] [blame] | 115 | override async objdump( |
| 116 | outputFilename, |
| 117 | result: any, |
| 118 | maxSize: number, |
| 119 | intelAsm, |
| 120 | demangle, |
Jeremy Rifkin | 6a6efae | 2023-01-29 13:22:30 -0500 | [diff] [blame] | 121 | staticReloc: boolean, |
| 122 | dynamicReloc: boolean, |
Marc Poulhiès | 2fa2bbb | 2022-11-28 21:37:15 +0100 | [diff] [blame] | 123 | filters: ParseFiltersAndOutputOptions, |
| 124 | ) { |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 125 | outputFilename = this.getObjdumpOutputFilename(outputFilename); |
| 126 | |
Patrick Quist | 54c9cfd | 2022-08-25 23:31:37 +0200 | [diff] [blame] | 127 | // sometimes (with +z80 for example) the .bin file is written and the .s file is empty |
Matt Godbolt | 749319f | 2022-12-28 11:42:14 -0600 | [diff] [blame] | 128 | if (await utils.fileExists(outputFilename + '.bin')) { |
| 129 | outputFilename += '.bin'; |
| 130 | } else { |
| 131 | if (await utils.fileExists(outputFilename + '.s')) { |
| 132 | outputFilename += '.s'; |
| 133 | } else { |
Patrick Quist | 54c9cfd | 2022-08-25 23:31:37 +0200 | [diff] [blame] | 134 | result.asm = '<No output file ' + outputFilename + '.s>'; |
| 135 | return result; |
Patrick Quist | 54c9cfd | 2022-08-25 23:31:37 +0200 | [diff] [blame] | 136 | } |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 137 | } |
| 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 Godbolt | 749319f | 2022-12-28 11:42:14 -0600 | [diff] [blame] | 156 | if (objResult.code === 0) { |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 157 | result.objdumpTime = objResult.execTime; |
| 158 | result.asm = this.postProcessObjdumpOutput(objResult.stdout); |
Matt Godbolt | 749319f | 2022-12-28 11:42:14 -0600 | [diff] [blame] | 159 | } else { |
| 160 | logger.error(`Error executing objdump ${this.compiler.objdumper}`, objResult); |
| 161 | result.asm = `<No output: objdump returned ${objResult.code}>`; |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 162 | } |
| 163 | } |
| 164 | |
Patrick Quist | 64ce939 | 2022-09-23 17:21:45 +0200 | [diff] [blame] | 165 | if (result.code === 0 && filters.binary) { |
| 166 | const tapeFilepath = path.join(result.dirPath, this.getTapefilename()); |
partouf | 66e2ecf | 2022-09-23 19:00:09 +0200 | [diff] [blame] | 167 | if (await utils.fileExists(tapeFilepath)) { |
Patrick Quist | 092ce12 | 2023-01-11 21:07:38 +0100 | [diff] [blame] | 168 | await this.addArtifactToResult(result, tapeFilepath, ArtifactType.zxtape); |
partouf | 82deb60 | 2022-09-23 17:45:41 +0200 | [diff] [blame] | 169 | } |
Patrick Quist | 997a2d3 | 2022-09-25 23:02:13 +0200 | [diff] [blame] | 170 | |
| 171 | const smsFilepath = path.join(result.dirPath, this.getSmsfilename()); |
| 172 | if (await utils.fileExists(smsFilepath)) { |
Patrick Quist | 092ce12 | 2023-01-11 21:07:38 +0100 | [diff] [blame] | 173 | await this.addArtifactToResult(result, smsFilepath, ArtifactType.smsrom); |
Patrick Quist | 997a2d3 | 2022-09-25 23:02:13 +0200 | [diff] [blame] | 174 | } |
Patrick Quist | 64ce939 | 2022-09-23 17:21:45 +0200 | [diff] [blame] | 175 | } |
| 176 | |
Patrick Quist | 3f6004b | 2022-08-25 22:44:48 +0200 | [diff] [blame] | 177 | return result; |
| 178 | } |
| 179 | } |