mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
## Summary - Extracted source line handling logic into a dedicated `SourceLineHandler` class that consolidates .loc, .stabs, and .6502 directive parsing - Extracted label processing logic into a `LabelProcessor` class with methods for finding used labels and filtering - Created a `ParsingState` class to manage parsing loop state variables in a centralized way - Fully integrated all components into the main `AsmParser` class, replacing the original complex parsing loop ## Changes Made - **SourceLineHandler**: Unifies `.loc`, `.d2line`, `.cv_loc`, `.dbg`, `.stabn`, and 6502 debug directive parsing - **LabelProcessor**: Handles complex label detection, filtering, and cleanup logic with MIPS/non-MIPS support - **ParsingState**: Encapsulates state management during parsing (inNvccCode, inCustomAssembly, etc.) - **Integration**: All components work together through well-defined interfaces ## Verification - ✅ All 1082+ tests pass, including new subclass compatibility tests from PR #7779 - ✅ All 670+ filter tests pass, confirming exact behavior preservation - ✅ Added comprehensive unit tests for all new components (32 tests total) - ✅ TypeScript compilation and linting pass - ✅ No performance regression in core functionality ## Bug Fix Discovered The refactoring inadvertently **fixes issue #7781** - EWAVR label detection bug: - **Before**: EWAVR couldn't find labels in usage contexts like `ldi r16, HIGH(_data)` due to `labelFindFor()` returning definition regex - **After**: Now correctly uses `identifierFindRe` to find labels in usage contexts - Updated tests to reflect the corrected behavior ## Benefits - Reduced complexity in the main `processAsm` method (from 180+ lines to more manageable chunks) - Extracted highly testable, focused components with single responsibilities - Eliminated code duplication between source handling methods - Centralized state management reduces scattered variable handling - Maintained full backward compatibility and exact behavior - Fixed EWAVR label detection bug as a side effect 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <noreply@anthropic.com>
132 lines
4.2 KiB
TypeScript
132 lines
4.2 KiB
TypeScript
// Copyright (c) 2025, 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
|
|
// 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.
|
|
|
|
import {AsmResultSource} from '../../types/asmresult/asmresult.interfaces.js';
|
|
|
|
export class ParsingState {
|
|
public mayRemovePreviousLabel = true;
|
|
public keepInlineCode = false;
|
|
public lastOwnSource: AsmResultSource | undefined | null = null;
|
|
public inNvccDef = false;
|
|
public inNvccCode = false;
|
|
public inCustomAssembly = 0;
|
|
public inVLIWpacket = false;
|
|
private currentIndex = 0;
|
|
|
|
constructor(
|
|
public files: Record<number, string>,
|
|
public source: AsmResultSource | undefined | null,
|
|
public prevLabel: string,
|
|
public prevLabelIsUserFunction: boolean,
|
|
public dontMaskFilenames: boolean,
|
|
private asmLines: string[],
|
|
) {}
|
|
|
|
getCurrentLineIndex(): number {
|
|
return this.currentIndex;
|
|
}
|
|
|
|
*[Symbol.iterator](): Generator<string, void, unknown> {
|
|
while (this.currentIndex < this.asmLines.length) {
|
|
const line = this.asmLines[this.currentIndex];
|
|
this.currentIndex++;
|
|
yield line;
|
|
}
|
|
}
|
|
|
|
updateSource(newSource: AsmResultSource | null | undefined) {
|
|
this.source = newSource;
|
|
if (newSource?.file === null || newSource?.mainsource) {
|
|
this.lastOwnSource = newSource;
|
|
}
|
|
}
|
|
|
|
resetToBlockEnd() {
|
|
this.source = null;
|
|
this.prevLabel = '';
|
|
this.lastOwnSource = null;
|
|
}
|
|
|
|
enterCustomAssembly() {
|
|
this.inCustomAssembly++;
|
|
}
|
|
|
|
exitCustomAssembly() {
|
|
this.inCustomAssembly--;
|
|
}
|
|
|
|
isInCustomAssembly(): boolean {
|
|
return this.inCustomAssembly > 0;
|
|
}
|
|
|
|
setVLIWPacket(inVLIWpacket: boolean) {
|
|
this.inVLIWpacket = inVLIWpacket;
|
|
}
|
|
|
|
enterNvccDef() {
|
|
this.inNvccDef = true;
|
|
this.inNvccCode = true;
|
|
}
|
|
|
|
exitNvccDef() {
|
|
this.inNvccDef = false;
|
|
}
|
|
|
|
shouldFilterLibraryCode(filters: {libraryCode?: boolean}): boolean {
|
|
const isLibraryCodeFilterEnabled = Boolean(filters.libraryCode);
|
|
const isNotUserFunction = !this.prevLabelIsUserFunction;
|
|
const hasNoLastOwnSource = !this.lastOwnSource;
|
|
const hasSourceFile = Boolean(this.source?.file);
|
|
const isNotMainSource = !this.source?.mainsource;
|
|
|
|
return (
|
|
isLibraryCodeFilterEnabled && isNotUserFunction && hasNoLastOwnSource && hasSourceFile && isNotMainSource
|
|
);
|
|
}
|
|
|
|
shouldRemovePreviousLabel(): boolean {
|
|
return this.mayRemovePreviousLabel;
|
|
}
|
|
|
|
setMayRemovePreviousLabel(value: boolean) {
|
|
this.mayRemovePreviousLabel = value;
|
|
}
|
|
|
|
setKeepInlineCode(value: boolean) {
|
|
this.keepInlineCode = value;
|
|
}
|
|
|
|
shouldKeepInlineCode(): boolean {
|
|
return this.keepInlineCode;
|
|
}
|
|
|
|
updatePrevLabel(label: string, isUserFunction = false) {
|
|
this.prevLabel = label;
|
|
this.prevLabelIsUserFunction = isUserFunction;
|
|
}
|
|
|
|
clearPrevLabel() {
|
|
this.prevLabel = '';
|
|
this.prevLabelIsUserFunction = false;
|
|
}
|
|
}
|