@jhlagado/azm 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -78
- package/dist/src/api-compile.d.ts +0 -2
- package/dist/src/api-compile.js +2 -9
- package/dist/src/assembly/address-planning.js +21 -1
- package/dist/src/assembly/program-emission.js +1 -0
- package/dist/src/cli/parse-args.d.ts +0 -1
- package/dist/src/cli/parse-args.js +0 -7
- package/dist/src/cli/write-artifacts.js +0 -11
- package/dist/src/core/compile.js +192 -9
- package/dist/src/expansion/op-expansion.js +2 -0
- package/dist/src/model/expression.d.ts +4 -0
- package/dist/src/model/source-item.d.ts +11 -0
- package/dist/src/outputs/index.js +0 -2
- package/dist/src/outputs/types.d.ts +3 -16
- package/dist/src/outputs/write-asm80.js +206 -5
- package/dist/src/register-care/analyze.js +36 -8
- package/dist/src/register-care/annotations.js +33 -146
- package/dist/src/register-care/fix.d.ts +2 -0
- package/dist/src/register-care/fix.js +52 -0
- package/dist/src/register-care/instruction-shape.d.ts +11 -0
- package/dist/src/register-care/instruction-shape.js +129 -0
- package/dist/src/register-care/liveness.js +15 -7
- package/dist/src/register-care/profiles.js +4 -0
- package/dist/src/register-care/programModel.js +79 -13
- package/dist/src/register-care/report.d.ts +2 -1
- package/dist/src/register-care/report.js +91 -34
- package/dist/src/register-care/routine-summaries.d.ts +6 -0
- package/dist/src/register-care/routine-summaries.js +89 -0
- package/dist/src/register-care/summaries.d.ts +3 -3
- package/dist/src/register-care/summaries.js +42 -75
- package/dist/{legacy-root-azm/src/registerCare → src/register-care}/summary.js +33 -51
- package/dist/src/register-care/types.d.ts +6 -1
- package/dist/src/semantics/expression-evaluation.d.ts +7 -3
- package/dist/src/semantics/expression-evaluation.js +57 -0
- package/dist/src/source/strip-line-comment.d.ts +2 -0
- package/dist/src/source/strip-line-comment.js +26 -0
- package/dist/src/syntax/directive-aliases.js +9 -10
- package/dist/src/syntax/parse-diagnostics.d.ts +12 -0
- package/dist/src/syntax/parse-diagnostics.js +18 -0
- package/dist/src/syntax/parse-expression.js +34 -9
- package/dist/src/syntax/parse-line.js +150 -54
- package/dist/src/tooling/case-style.js +3 -0
- package/docs/reference/cli.md +6 -4
- package/docs/reference/tooling-api.md +13 -9
- package/package.json +4 -6
- package/dist/legacy-root-azm/src/analysis.d.ts +0 -11
- package/dist/legacy-root-azm/src/analysis.js +0 -41
- package/dist/legacy-root-azm/src/compile.d.ts +0 -10
- package/dist/legacy-root-azm/src/compile.js +0 -186
- package/dist/legacy-root-azm/src/compileShared.d.ts +0 -3
- package/dist/legacy-root-azm/src/compileShared.js +0 -7
- package/dist/legacy-root-azm/src/diagnosticTypes.d.ts +0 -77
- package/dist/legacy-root-azm/src/diagnosticTypes.js +0 -53
- package/dist/legacy-root-azm/src/formats/index.d.ts +0 -7
- package/dist/legacy-root-azm/src/formats/index.js +0 -17
- package/dist/legacy-root-azm/src/formats/range.d.ts +0 -17
- package/dist/legacy-root-azm/src/formats/range.js +0 -45
- package/dist/legacy-root-azm/src/formats/types.d.ts +0 -283
- package/dist/legacy-root-azm/src/formats/types.js +0 -1
- package/dist/legacy-root-azm/src/formats/writeAsm80.d.ts +0 -6
- package/dist/legacy-root-azm/src/formats/writeAsm80.js +0 -86
- package/dist/legacy-root-azm/src/formats/writeBin.d.ts +0 -7
- package/dist/legacy-root-azm/src/formats/writeBin.js +0 -23
- package/dist/legacy-root-azm/src/formats/writeD8m.d.ts +0 -9
- package/dist/legacy-root-azm/src/formats/writeD8m.js +0 -245
- package/dist/legacy-root-azm/src/formats/writeHex.d.ts +0 -8
- package/dist/legacy-root-azm/src/formats/writeHex.js +0 -38
- package/dist/legacy-root-azm/src/formats/writeListing.d.ts +0 -8
- package/dist/legacy-root-azm/src/formats/writeListing.js +0 -83
- package/dist/legacy-root-azm/src/frontend/asm80/asmLine.d.ts +0 -39
- package/dist/legacy-root-azm/src/frontend/asm80/asmLine.js +0 -89
- package/dist/legacy-root-azm/src/frontend/asm80/parseAsmRawValues.d.ts +0 -4
- package/dist/legacy-root-azm/src/frontend/asm80/parseAsmRawValues.js +0 -94
- package/dist/legacy-root-azm/src/frontend/asm80/quoteScan.d.ts +0 -10
- package/dist/legacy-root-azm/src/frontend/asm80/quoteScan.js +0 -25
- package/dist/legacy-root-azm/src/frontend/ast.d.ts +0 -376
- package/dist/legacy-root-azm/src/frontend/ast.js +0 -1
- package/dist/legacy-root-azm/src/frontend/directiveAliases.d.ts +0 -14
- package/dist/legacy-root-azm/src/frontend/directiveAliases.js +0 -189
- package/dist/legacy-root-azm/src/frontend/grammarData.d.ts +0 -14
- package/dist/legacy-root-azm/src/frontend/grammarData.js +0 -65
- package/dist/legacy-root-azm/src/frontend/immExprUtils.d.ts +0 -2
- package/dist/legacy-root-azm/src/frontend/immExprUtils.js +0 -12
- package/dist/legacy-root-azm/src/frontend/parseAsmFlatDirectiveLine.d.ts +0 -17
- package/dist/legacy-root-azm/src/frontend/parseAsmFlatDirectiveLine.js +0 -187
- package/dist/legacy-root-azm/src/frontend/parseAsmInstruction.d.ts +0 -3
- package/dist/legacy-root-azm/src/frontend/parseAsmInstruction.js +0 -73
- package/dist/legacy-root-azm/src/frontend/parseAsmStatements.d.ts +0 -6
- package/dist/legacy-root-azm/src/frontend/parseAsmStatements.js +0 -16
- package/dist/legacy-root-azm/src/frontend/parseAsmStream.d.ts +0 -10
- package/dist/legacy-root-azm/src/frontend/parseAsmStream.js +0 -33
- package/dist/legacy-root-azm/src/frontend/parseAsmTopLevel.d.ts +0 -18
- package/dist/legacy-root-azm/src/frontend/parseAsmTopLevel.js +0 -34
- package/dist/legacy-root-azm/src/frontend/parseDiagnostics.d.ts +0 -9
- package/dist/legacy-root-azm/src/frontend/parseDiagnostics.js +0 -16
- package/dist/legacy-root-azm/src/frontend/parseEnum.d.ts +0 -12
- package/dist/legacy-root-azm/src/frontend/parseEnum.js +0 -70
- package/dist/legacy-root-azm/src/frontend/parseImm.d.ts +0 -10
- package/dist/legacy-root-azm/src/frontend/parseImm.js +0 -397
- package/dist/legacy-root-azm/src/frontend/parseLogicalLines.d.ts +0 -11
- package/dist/legacy-root-azm/src/frontend/parseLogicalLines.js +0 -94
- package/dist/legacy-root-azm/src/frontend/parseOp.d.ts +0 -25
- package/dist/legacy-root-azm/src/frontend/parseOp.js +0 -120
- package/dist/legacy-root-azm/src/frontend/parseOpHeader.d.ts +0 -20
- package/dist/legacy-root-azm/src/frontend/parseOpHeader.js +0 -32
- package/dist/legacy-root-azm/src/frontend/parseOperands.d.ts +0 -4
- package/dist/legacy-root-azm/src/frontend/parseOperands.js +0 -290
- package/dist/legacy-root-azm/src/frontend/parseParams.d.ts +0 -6
- package/dist/legacy-root-azm/src/frontend/parseParams.js +0 -62
- package/dist/legacy-root-azm/src/frontend/parseParserRecovery.d.ts +0 -12
- package/dist/legacy-root-azm/src/frontend/parseParserRecovery.js +0 -17
- package/dist/legacy-root-azm/src/frontend/parseParserShared.d.ts +0 -2
- package/dist/legacy-root-azm/src/frontend/parseParserShared.js +0 -8
- package/dist/legacy-root-azm/src/frontend/parseRawDataDirectiveStart.d.ts +0 -1
- package/dist/legacy-root-azm/src/frontend/parseRawDataDirectiveStart.js +0 -3
- package/dist/legacy-root-azm/src/frontend/parseRawDataDirectives.d.ts +0 -7
- package/dist/legacy-root-azm/src/frontend/parseRawDataDirectives.js +0 -142
- package/dist/legacy-root-azm/src/frontend/parseRecordFieldDecl.d.ts +0 -34
- package/dist/legacy-root-azm/src/frontend/parseRecordFieldDecl.js +0 -177
- package/dist/legacy-root-azm/src/frontend/parseSourceItemDispatch.d.ts +0 -46
- package/dist/legacy-root-azm/src/frontend/parseSourceItemDispatch.js +0 -53
- package/dist/legacy-root-azm/src/frontend/parseSourceItemTable.d.ts +0 -16
- package/dist/legacy-root-azm/src/frontend/parseSourceItemTable.js +0 -68
- package/dist/legacy-root-azm/src/frontend/parseTopLevelCommon.d.ts +0 -11
- package/dist/legacy-root-azm/src/frontend/parseTopLevelCommon.js +0 -50
- package/dist/legacy-root-azm/src/frontend/parseTypes.d.ts +0 -24
- package/dist/legacy-root-azm/src/frontend/parseTypes.js +0 -77
- package/dist/legacy-root-azm/src/frontend/parser.d.ts +0 -11
- package/dist/legacy-root-azm/src/frontend/parser.js +0 -88
- package/dist/legacy-root-azm/src/frontend/source.d.ts +0 -28
- package/dist/legacy-root-azm/src/frontend/source.js +0 -58
- package/dist/legacy-root-azm/src/frontend/sourceExtensions.d.ts +0 -2
- package/dist/legacy-root-azm/src/frontend/sourceExtensions.js +0 -6
- package/dist/legacy-root-azm/src/lintCaseStyle.d.ts +0 -4
- package/dist/legacy-root-azm/src/lintCaseStyle.js +0 -129
- package/dist/legacy-root-azm/src/lowering/asmDirectiveLowering.d.ts +0 -4
- package/dist/legacy-root-azm/src/lowering/asmDirectiveLowering.js +0 -229
- package/dist/legacy-root-azm/src/lowering/asmDirectiveTraversal.d.ts +0 -47
- package/dist/legacy-root-azm/src/lowering/asmDirectiveTraversal.js +0 -52
- package/dist/legacy-root-azm/src/lowering/asmEquResolution.d.ts +0 -8
- package/dist/legacy-root-azm/src/lowering/asmEquResolution.js +0 -69
- package/dist/legacy-root-azm/src/lowering/asmInstructionLdHelpers.d.ts +0 -15
- package/dist/legacy-root-azm/src/lowering/asmInstructionLdHelpers.js +0 -102
- package/dist/legacy-root-azm/src/lowering/asmInstructionLowering.d.ts +0 -5
- package/dist/legacy-root-azm/src/lowering/asmInstructionLowering.js +0 -54
- package/dist/legacy-root-azm/src/lowering/asmInstructionStream.d.ts +0 -46
- package/dist/legacy-root-azm/src/lowering/asmInstructionStream.js +0 -51
- package/dist/legacy-root-azm/src/lowering/asmLoweringBranchCall.d.ts +0 -43
- package/dist/legacy-root-azm/src/lowering/asmLoweringBranchCall.js +0 -254
- package/dist/legacy-root-azm/src/lowering/asmLoweringHost.d.ts +0 -23
- package/dist/legacy-root-azm/src/lowering/asmLoweringHost.js +0 -1
- package/dist/legacy-root-azm/src/lowering/asmLoweringLd.d.ts +0 -28
- package/dist/legacy-root-azm/src/lowering/asmLoweringLd.js +0 -144
- package/dist/legacy-root-azm/src/lowering/asmRangeLowering.d.ts +0 -17
- package/dist/legacy-root-azm/src/lowering/asmRangeLowering.js +0 -39
- package/dist/legacy-root-azm/src/lowering/asmRawDataLowering.d.ts +0 -16
- package/dist/legacy-root-azm/src/lowering/asmRawDataLowering.js +0 -209
- package/dist/legacy-root-azm/src/lowering/asmSourceEmitter.d.ts +0 -4
- package/dist/legacy-root-azm/src/lowering/asmSourceEmitter.js +0 -9
- package/dist/legacy-root-azm/src/lowering/asmSourceInstructionLowering.d.ts +0 -4
- package/dist/legacy-root-azm/src/lowering/asmSourceInstructionLowering.js +0 -14
- package/dist/legacy-root-azm/src/lowering/asmUtils.d.ts +0 -13
- package/dist/legacy-root-azm/src/lowering/asmUtils.js +0 -105
- package/dist/legacy-root-azm/src/lowering/assemblerFlowSetup.d.ts +0 -54
- package/dist/legacy-root-azm/src/lowering/assemblerFlowSetup.js +0 -128
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringContext.d.ts +0 -151
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringContext.js +0 -16
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringContextSplit.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringContextSplit.js +0 -75
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringPhases.d.ts +0 -66
- package/dist/legacy-root-azm/src/lowering/assemblerLoweringPhases.js +0 -166
- package/dist/legacy-root-azm/src/lowering/bytePlacement.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/bytePlacement.js +0 -37
- package/dist/legacy-root-azm/src/lowering/capabilities.d.ts +0 -67
- package/dist/legacy-root-azm/src/lowering/capabilities.js +0 -1
- package/dist/legacy-root-azm/src/lowering/eaResolution.d.ts +0 -58
- package/dist/legacy-root-azm/src/lowering/eaResolution.js +0 -159
- package/dist/legacy-root-azm/src/lowering/emissionCore.d.ts +0 -17
- package/dist/legacy-root-azm/src/lowering/emissionCore.js +0 -21
- package/dist/legacy-root-azm/src/lowering/emit.d.ts +0 -17
- package/dist/legacy-root-azm/src/lowering/emit.js +0 -46
- package/dist/legacy-root-azm/src/lowering/emitContextBuilder.d.ts +0 -63
- package/dist/legacy-root-azm/src/lowering/emitContextBuilder.js +0 -41
- package/dist/legacy-root-azm/src/lowering/emitFinalization.d.ts +0 -61
- package/dist/legacy-root-azm/src/lowering/emitFinalization.js +0 -66
- package/dist/legacy-root-azm/src/lowering/emitFinalizationSetup.d.ts +0 -19
- package/dist/legacy-root-azm/src/lowering/emitFinalizationSetup.js +0 -26
- package/dist/legacy-root-azm/src/lowering/emitPhase1BuildProgramLoweringContext.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/emitPhase1BuildProgramLoweringContext.js +0 -119
- package/dist/legacy-root-azm/src/lowering/emitPhase1Helpers.d.ts +0 -4
- package/dist/legacy-root-azm/src/lowering/emitPhase1Helpers.js +0 -12
- package/dist/legacy-root-azm/src/lowering/emitPhase1Types.d.ts +0 -21
- package/dist/legacy-root-azm/src/lowering/emitPhase1Types.js +0 -1
- package/dist/legacy-root-azm/src/lowering/emitPhase1WirePipeline.d.ts +0 -70
- package/dist/legacy-root-azm/src/lowering/emitPhase1WirePipeline.js +0 -203
- package/dist/legacy-root-azm/src/lowering/emitPhase1Workspace.d.ts +0 -82
- package/dist/legacy-root-azm/src/lowering/emitPhase1Workspace.js +0 -55
- package/dist/legacy-root-azm/src/lowering/emitPipeline.d.ts +0 -121
- package/dist/legacy-root-azm/src/lowering/emitPipeline.js +0 -57
- package/dist/legacy-root-azm/src/lowering/emitProgramContext.d.ts +0 -39
- package/dist/legacy-root-azm/src/lowering/emitProgramContext.js +0 -29
- package/dist/legacy-root-azm/src/lowering/emitState.d.ts +0 -90
- package/dist/legacy-root-azm/src/lowering/emitState.js +0 -124
- package/dist/legacy-root-azm/src/lowering/fixupBaseResolution.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/fixupBaseResolution.js +0 -23
- package/dist/legacy-root-azm/src/lowering/fixupEmission.d.ts +0 -64
- package/dist/legacy-root-azm/src/lowering/fixupEmission.js +0 -199
- package/dist/legacy-root-azm/src/lowering/immMath.d.ts +0 -2
- package/dist/legacy-root-azm/src/lowering/immMath.js +0 -34
- package/dist/legacy-root-azm/src/lowering/inputAssets.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/inputAssets.js +0 -106
- package/dist/legacy-root-azm/src/lowering/ldEncoding.d.ts +0 -15
- package/dist/legacy-root-azm/src/lowering/ldEncoding.js +0 -12
- package/dist/legacy-root-azm/src/lowering/ldEncodingRegMemHelpers.d.ts +0 -5
- package/dist/legacy-root-azm/src/lowering/ldEncodingRegMemHelpers.js +0 -124
- package/dist/legacy-root-azm/src/lowering/ldFormSelection.d.ts +0 -26
- package/dist/legacy-root-azm/src/lowering/ldFormSelection.js +0 -92
- package/dist/legacy-root-azm/src/lowering/ldLowering.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/ldLowering.js +0 -13
- package/dist/legacy-root-azm/src/lowering/loweredAsmByteEmission.d.ts +0 -23
- package/dist/legacy-root-azm/src/lowering/loweredAsmByteEmission.js +0 -185
- package/dist/legacy-root-azm/src/lowering/loweredAsmPlacement.d.ts +0 -13
- package/dist/legacy-root-azm/src/lowering/loweredAsmPlacement.js +0 -86
- package/dist/legacy-root-azm/src/lowering/loweredAsmStreamRecording.d.ts +0 -27
- package/dist/legacy-root-azm/src/lowering/loweredAsmStreamRecording.js +0 -215
- package/dist/legacy-root-azm/src/lowering/loweredAsmTypes.d.ts +0 -202
- package/dist/legacy-root-azm/src/lowering/loweredAsmTypes.js +0 -1
- package/dist/legacy-root-azm/src/lowering/loweredFormat.d.ts +0 -3
- package/dist/legacy-root-azm/src/lowering/loweredFormat.js +0 -26
- package/dist/legacy-root-azm/src/lowering/loweredItemSize.d.ts +0 -4
- package/dist/legacy-root-azm/src/lowering/loweredItemSize.js +0 -17
- package/dist/legacy-root-azm/src/lowering/loweringDiagnostics.d.ts +0 -9
- package/dist/legacy-root-azm/src/lowering/loweringDiagnostics.js +0 -55
- package/dist/legacy-root-azm/src/lowering/loweringTypes.d.ts +0 -27
- package/dist/legacy-root-azm/src/lowering/loweringTypes.js +0 -1
- package/dist/legacy-root-azm/src/lowering/opCandidateRegistry.d.ts +0 -9
- package/dist/legacy-root-azm/src/lowering/opCandidateRegistry.js +0 -9
- package/dist/legacy-root-azm/src/lowering/opExpansionExecution.d.ts +0 -15
- package/dist/legacy-root-azm/src/lowering/opExpansionExecution.js +0 -45
- package/dist/legacy-root-azm/src/lowering/opExpansionOrchestration.d.ts +0 -15
- package/dist/legacy-root-azm/src/lowering/opExpansionOrchestration.js +0 -88
- package/dist/legacy-root-azm/src/lowering/opExpansionStream.d.ts +0 -12
- package/dist/legacy-root-azm/src/lowering/opExpansionStream.js +0 -176
- package/dist/legacy-root-azm/src/lowering/opMatching.d.ts +0 -52
- package/dist/legacy-root-azm/src/lowering/opMatching.js +0 -355
- package/dist/legacy-root-azm/src/lowering/opSubstitution.d.ts +0 -13
- package/dist/legacy-root-azm/src/lowering/opSubstitution.js +0 -175
- package/dist/legacy-root-azm/src/lowering/prescanTypes.d.ts +0 -7
- package/dist/legacy-root-azm/src/lowering/prescanTypes.js +0 -1
- package/dist/legacy-root-azm/src/lowering/programLowering.d.ts +0 -144
- package/dist/legacy-root-azm/src/lowering/programLowering.js +0 -2
- package/dist/legacy-root-azm/src/lowering/programLoweringDeclarations.d.ts +0 -5
- package/dist/legacy-root-azm/src/lowering/programLoweringDeclarations.js +0 -5
- package/dist/legacy-root-azm/src/lowering/programLoweringFinalize.d.ts +0 -18
- package/dist/legacy-root-azm/src/lowering/programLoweringFinalize.js +0 -115
- package/dist/legacy-root-azm/src/lowering/programLoweringTraversal.d.ts +0 -2
- package/dist/legacy-root-azm/src/lowering/programLoweringTraversal.js +0 -93
- package/dist/legacy-root-azm/src/lowering/programPrescan.d.ts +0 -3
- package/dist/legacy-root-azm/src/lowering/programPrescan.js +0 -37
- package/dist/legacy-root-azm/src/lowering/traceFormat.d.ts +0 -13
- package/dist/legacy-root-azm/src/lowering/traceFormat.js +0 -211
- package/dist/legacy-root-azm/src/packageInfo.d.ts +0 -1
- package/dist/legacy-root-azm/src/packageInfo.js +0 -15
- package/dist/legacy-root-azm/src/pathCompare.d.ts +0 -3
- package/dist/legacy-root-azm/src/pathCompare.js +0 -26
- package/dist/legacy-root-azm/src/pipeline.d.ts +0 -91
- package/dist/legacy-root-azm/src/pipeline.js +0 -1
- package/dist/legacy-root-azm/src/registerCare/analyze.d.ts +0 -24
- package/dist/legacy-root-azm/src/registerCare/analyze.js +0 -327
- package/dist/legacy-root-azm/src/registerCare/boundaryHints.d.ts +0 -2
- package/dist/legacy-root-azm/src/registerCare/boundaryHints.js +0 -10
- package/dist/legacy-root-azm/src/registerCare/carriers.d.ts +0 -4
- package/dist/legacy-root-azm/src/registerCare/carriers.js +0 -78
- package/dist/legacy-root-azm/src/registerCare/controlFlow.d.ts +0 -5
- package/dist/legacy-root-azm/src/registerCare/controlFlow.js +0 -35
- package/dist/legacy-root-azm/src/registerCare/fix.d.ts +0 -11
- package/dist/legacy-root-azm/src/registerCare/fix.js +0 -119
- package/dist/legacy-root-azm/src/registerCare/liveness.d.ts +0 -7
- package/dist/legacy-root-azm/src/registerCare/liveness.js +0 -227
- package/dist/legacy-root-azm/src/registerCare/profiles.d.ts +0 -11
- package/dist/legacy-root-azm/src/registerCare/profiles.js +0 -45
- package/dist/legacy-root-azm/src/registerCare/programModel.d.ts +0 -3
- package/dist/legacy-root-azm/src/registerCare/programModel.js +0 -181
- package/dist/legacy-root-azm/src/registerCare/report.d.ts +0 -5
- package/dist/legacy-root-azm/src/registerCare/report.js +0 -139
- package/dist/legacy-root-azm/src/registerCare/smartComments.d.ts +0 -5
- package/dist/legacy-root-azm/src/registerCare/smartComments.js +0 -247
- package/dist/legacy-root-azm/src/registerCare/types.d.ts +0 -154
- package/dist/legacy-root-azm/src/registerCare/types.js +0 -1
- package/dist/legacy-root-azm/src/semantics/declVisitor.d.ts +0 -5
- package/dist/legacy-root-azm/src/semantics/declVisitor.js +0 -11
- package/dist/legacy-root-azm/src/semantics/env.d.ts +0 -28
- package/dist/legacy-root-azm/src/semantics/env.js +0 -432
- package/dist/legacy-root-azm/src/semantics/layout.d.ts +0 -21
- package/dist/legacy-root-azm/src/semantics/layout.js +0 -226
- package/dist/legacy-root-azm/src/semantics/layoutCastFold.d.ts +0 -22
- package/dist/legacy-root-azm/src/semantics/layoutCastFold.js +0 -118
- package/dist/legacy-root-azm/src/semantics/semanticsDiagnostics.d.ts +0 -2
- package/dist/legacy-root-azm/src/semantics/semanticsDiagnostics.js +0 -4
- package/dist/legacy-root-azm/src/semantics/typeQueries.d.ts +0 -31
- package/dist/legacy-root-azm/src/semantics/typeQueries.js +0 -124
- package/dist/legacy-root-azm/src/sourceIncludeExpansion.d.ts +0 -17
- package/dist/legacy-root-azm/src/sourceIncludeExpansion.js +0 -124
- package/dist/legacy-root-azm/src/sourceIncludePaths.d.ts +0 -1
- package/dist/legacy-root-azm/src/sourceIncludePaths.js +0 -12
- package/dist/legacy-root-azm/src/sourceLoader.d.ts +0 -15
- package/dist/legacy-root-azm/src/sourceLoader.js +0 -118
- package/dist/legacy-root-azm/src/z80/effects.d.ts +0 -3
- package/dist/legacy-root-azm/src/z80/effects.js +0 -516
- package/dist/legacy-root-azm/src/z80/encode.d.ts +0 -10
- package/dist/legacy-root-azm/src/z80/encode.js +0 -412
- package/dist/legacy-root-azm/src/z80/encodeAlu.d.ts +0 -7
- package/dist/legacy-root-azm/src/z80/encodeAlu.js +0 -219
- package/dist/legacy-root-azm/src/z80/encodeBitOps.d.ts +0 -7
- package/dist/legacy-root-azm/src/z80/encodeBitOps.js +0 -123
- package/dist/legacy-root-azm/src/z80/encodeContext.d.ts +0 -29
- package/dist/legacy-root-azm/src/z80/encodeContext.js +0 -1
- package/dist/legacy-root-azm/src/z80/encodeControl.d.ts +0 -26
- package/dist/legacy-root-azm/src/z80/encodeControl.js +0 -180
- package/dist/legacy-root-azm/src/z80/encodeCoreOps.d.ts +0 -7
- package/dist/legacy-root-azm/src/z80/encodeCoreOps.js +0 -131
- package/dist/legacy-root-azm/src/z80/encodeIo.d.ts +0 -9
- package/dist/legacy-root-azm/src/z80/encodeIo.js +0 -128
- package/dist/legacy-root-azm/src/z80/encodeLd.d.ts +0 -13
- package/dist/legacy-root-azm/src/z80/encodeLd.js +0 -273
- package/dist/legacy-root-azm/src/z80/encoderRegistry.d.ts +0 -13
- package/dist/legacy-root-azm/src/z80/encoderRegistry.js +0 -169
- package/dist/src/outputs/write-listing.d.ts +0 -2
- package/dist/src/outputs/write-listing.js +0 -79
- /package/dist/{legacy-root-azm/src/registerCare → src/register-care}/annotate.d.ts +0 -0
- /package/dist/{legacy-root-azm/src/registerCare → src/register-care}/annotate.js +0 -0
- /package/dist/{legacy-root-azm/src/registerCare → src/register-care}/sourceText.d.ts +0 -0
- /package/dist/{legacy-root-azm/src/registerCare → src/register-care}/sourceText.js +0 -0
- /package/dist/{legacy-root-azm/src/registerCare → src/register-care}/summary.d.ts +0 -0
|
@@ -14,6 +14,7 @@ export function writeAsm80(items, symbols, opts = {}) {
|
|
|
14
14
|
void opts;
|
|
15
15
|
const evalContext = {
|
|
16
16
|
constants: collectConstants(symbols),
|
|
17
|
+
symbols: collectSymbolValues(symbols),
|
|
17
18
|
layouts: collectLayouts(items),
|
|
18
19
|
};
|
|
19
20
|
const lines = [asm80Header, ''];
|
|
@@ -43,6 +44,13 @@ function collectConstants(symbols) {
|
|
|
43
44
|
}
|
|
44
45
|
return constants;
|
|
45
46
|
}
|
|
47
|
+
function collectSymbolValues(symbols) {
|
|
48
|
+
const values = new Map();
|
|
49
|
+
for (const symbol of symbols) {
|
|
50
|
+
values.set(symbol.name, symbol.kind === 'constant' ? symbol.value : symbol.address);
|
|
51
|
+
}
|
|
52
|
+
return values;
|
|
53
|
+
}
|
|
46
54
|
function collectLayouts(items) {
|
|
47
55
|
const layouts = new Map();
|
|
48
56
|
for (const item of items) {
|
|
@@ -53,6 +61,13 @@ function collectLayouts(items) {
|
|
|
53
61
|
span: item.span,
|
|
54
62
|
});
|
|
55
63
|
}
|
|
64
|
+
else if (item.kind === 'type-alias') {
|
|
65
|
+
layouts.set(item.name, {
|
|
66
|
+
kind: 'alias',
|
|
67
|
+
typeExpr: item.typeExpr,
|
|
68
|
+
span: item.span,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
56
71
|
}
|
|
57
72
|
return layouts;
|
|
58
73
|
}
|
|
@@ -74,6 +89,11 @@ function formatItem(item, evalContext, state) {
|
|
|
74
89
|
? undefined
|
|
75
90
|
: withImplicitOrg(state, `${item.name} EQU ${expression}`, 0);
|
|
76
91
|
}
|
|
92
|
+
case 'comment':
|
|
93
|
+
return {
|
|
94
|
+
text: item.origin === 'user' ? `; ${item.text}` : `; AZM: ${item.text}`,
|
|
95
|
+
size: 0,
|
|
96
|
+
};
|
|
77
97
|
case 'label':
|
|
78
98
|
return withImplicitOrg(state, `${item.name}:`, 0);
|
|
79
99
|
case 'db':
|
|
@@ -90,6 +110,7 @@ function formatItem(item, evalContext, state) {
|
|
|
90
110
|
return withImplicitOrg(state, formatInstruction(item.instruction, evalContext)?.text, instructionSize(item.instruction));
|
|
91
111
|
case 'enum':
|
|
92
112
|
case 'type':
|
|
113
|
+
case 'type-alias':
|
|
93
114
|
case 'end':
|
|
94
115
|
case 'binfrom':
|
|
95
116
|
case 'binto':
|
|
@@ -239,6 +260,16 @@ function formatInstruction(instruction, evalContext) {
|
|
|
239
260
|
case 'res':
|
|
240
261
|
case 'set':
|
|
241
262
|
return formatBitOp(instruction, evalContext);
|
|
263
|
+
case 'rlc':
|
|
264
|
+
case 'rrc':
|
|
265
|
+
case 'rl':
|
|
266
|
+
case 'rr':
|
|
267
|
+
case 'sla':
|
|
268
|
+
case 'sra':
|
|
269
|
+
case 'sll':
|
|
270
|
+
case 'sls':
|
|
271
|
+
case 'srl':
|
|
272
|
+
return formatRotateShift(instruction, evalContext);
|
|
242
273
|
case 'in':
|
|
243
274
|
return formatIn(instruction, evalContext);
|
|
244
275
|
case 'out':
|
|
@@ -264,6 +295,11 @@ function formatInstruction(instruction, evalContext) {
|
|
|
264
295
|
return formatBranch(`call ${instruction.condition},`, instruction.expression, evalContext);
|
|
265
296
|
case 'djnz':
|
|
266
297
|
return formatBranch('djnz', instruction.expression, evalContext);
|
|
298
|
+
case 'push':
|
|
299
|
+
case 'pop':
|
|
300
|
+
return { text: `${instruction.mnemonic} ${instruction.register}` };
|
|
301
|
+
case 'ret-cc':
|
|
302
|
+
return { text: `ret ${instruction.condition}` };
|
|
267
303
|
default:
|
|
268
304
|
return undefined;
|
|
269
305
|
}
|
|
@@ -282,7 +318,7 @@ function formatAlu(mnemonic, source, evalContext) {
|
|
|
282
318
|
return { text: `${mnemonic} ${operand}` };
|
|
283
319
|
}
|
|
284
320
|
function formatAluOperand(source, evalContext) {
|
|
285
|
-
if (source.kind === 'reg8') {
|
|
321
|
+
if (source.kind === 'reg8' || source.kind === 'reg-half-index') {
|
|
286
322
|
return source.register;
|
|
287
323
|
}
|
|
288
324
|
if (source.kind === 'reg-indirect' && source.register === 'hl') {
|
|
@@ -330,6 +366,18 @@ function formatLd(target, source, evalContext) {
|
|
|
330
366
|
if (target.kind === 'reg8' && source.kind === 'reg8') {
|
|
331
367
|
return { text: `ld ${target.register}, ${source.register}` };
|
|
332
368
|
}
|
|
369
|
+
if (target.kind === 'reg8' && source.kind === 'reg-half-index') {
|
|
370
|
+
return { text: `ld ${target.register}, ${source.register}` };
|
|
371
|
+
}
|
|
372
|
+
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'special8') {
|
|
373
|
+
return { text: `ld a, ${source.register}` };
|
|
374
|
+
}
|
|
375
|
+
if (target.kind === 'special8' && source.kind === 'reg8' && source.register === 'a') {
|
|
376
|
+
return { text: `ld ${target.register}, a` };
|
|
377
|
+
}
|
|
378
|
+
if (target.kind === 'reg-index16' && source.kind === 'imm') {
|
|
379
|
+
return formatLdText(target.register, formatExpression(source.expression, evalContext, 'word'));
|
|
380
|
+
}
|
|
333
381
|
if (target.kind === 'reg16' && source.kind === 'imm') {
|
|
334
382
|
return formatLdText(target.register, formatExpression(source.expression, evalContext, 'word'));
|
|
335
383
|
}
|
|
@@ -345,12 +393,44 @@ function formatLd(target, source, evalContext) {
|
|
|
345
393
|
source.register === 'a') {
|
|
346
394
|
return { text: `ld (${target.register}), a` };
|
|
347
395
|
}
|
|
348
|
-
if (target.kind === 'reg8' &&
|
|
349
|
-
return
|
|
396
|
+
if (target.kind === 'reg8' && source.kind === 'reg-indirect' && source.register === 'hl') {
|
|
397
|
+
return { text: `ld ${target.register}, (hl)` };
|
|
398
|
+
}
|
|
399
|
+
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'reg8') {
|
|
400
|
+
return { text: `ld (hl), ${source.register}` };
|
|
401
|
+
}
|
|
402
|
+
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'imm') {
|
|
403
|
+
const value = formatExpression(source.expression, evalContext, 'byte');
|
|
404
|
+
return value === undefined ? undefined : { text: `ld (hl), ${value}` };
|
|
405
|
+
}
|
|
406
|
+
if (target.kind === 'reg8' && source.kind === 'indexed') {
|
|
407
|
+
const memory = formatIndexedMemory(source.register, source.displacement, evalContext);
|
|
408
|
+
return memory === undefined ? undefined : { text: `ld ${target.register}, ${memory}` };
|
|
409
|
+
}
|
|
410
|
+
if (target.kind === 'indexed' && source.kind === 'reg8') {
|
|
411
|
+
const memory = formatIndexedMemory(target.register, target.displacement, evalContext);
|
|
412
|
+
return memory === undefined ? undefined : { text: `ld ${memory}, ${source.register}` };
|
|
413
|
+
}
|
|
414
|
+
if (target.kind === 'reg8' && source.kind === 'mem-abs') {
|
|
415
|
+
return formatLdText(target.register, formatParenthesizedExpression(source.expression, evalContext, 'auto'));
|
|
350
416
|
}
|
|
351
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg8'
|
|
417
|
+
if (target.kind === 'mem-abs' && source.kind === 'reg8') {
|
|
352
418
|
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
353
|
-
return targetText === undefined
|
|
419
|
+
return targetText === undefined
|
|
420
|
+
? undefined
|
|
421
|
+
: { text: `ld ${targetText}, ${source.register}` };
|
|
422
|
+
}
|
|
423
|
+
if (target.kind === 'mem-abs' && source.kind === 'reg16') {
|
|
424
|
+
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
425
|
+
return targetText === undefined
|
|
426
|
+
? undefined
|
|
427
|
+
: { text: `ld ${targetText}, ${source.register}` };
|
|
428
|
+
}
|
|
429
|
+
if (target.kind === 'mem-abs' && source.kind === 'reg-index16') {
|
|
430
|
+
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
431
|
+
return targetText === undefined
|
|
432
|
+
? undefined
|
|
433
|
+
: { text: `ld ${targetText}, ${source.register}` };
|
|
354
434
|
}
|
|
355
435
|
return undefined;
|
|
356
436
|
}
|
|
@@ -383,6 +463,37 @@ function formatExpression(expression, evalContext, width) {
|
|
|
383
463
|
if (expression.kind === 'symbol') {
|
|
384
464
|
return expression.name;
|
|
385
465
|
}
|
|
466
|
+
if (expression.kind === 'type-size') {
|
|
467
|
+
const value = evaluateLoweredConstant(expression, evalContext);
|
|
468
|
+
return value === undefined ? expression.typeExpr.name : formatLoweredNumber(value, width);
|
|
469
|
+
}
|
|
470
|
+
if (expression.kind === 'current-location') {
|
|
471
|
+
return '$';
|
|
472
|
+
}
|
|
473
|
+
if (expression.kind === 'unary') {
|
|
474
|
+
const inner = formatExpression(expression.expression, evalContext, width);
|
|
475
|
+
if (inner === undefined) {
|
|
476
|
+
return undefined;
|
|
477
|
+
}
|
|
478
|
+
switch (expression.operator) {
|
|
479
|
+
case '+':
|
|
480
|
+
return inner;
|
|
481
|
+
case '-':
|
|
482
|
+
return `-${inner}`;
|
|
483
|
+
case '~': {
|
|
484
|
+
const value = evaluateLoweredConstant(expression, evalContext);
|
|
485
|
+
return value === undefined ? undefined : formatLoweredNumber(value, width);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (expression.kind === 'binary') {
|
|
490
|
+
const left = formatExpression(expression.left, evalContext, width);
|
|
491
|
+
const right = formatExpression(expression.right, evalContext, width);
|
|
492
|
+
if (left === undefined || right === undefined) {
|
|
493
|
+
return undefined;
|
|
494
|
+
}
|
|
495
|
+
return `${left}${expression.operator}${right}`;
|
|
496
|
+
}
|
|
386
497
|
return undefined;
|
|
387
498
|
}
|
|
388
499
|
function evaluateLoweredConstant(expression, evalContext) {
|
|
@@ -391,12 +502,31 @@ function evaluateLoweredConstant(expression, evalContext) {
|
|
|
391
502
|
return expression.value;
|
|
392
503
|
case 'symbol':
|
|
393
504
|
return evalContext.constants.get(expression.name);
|
|
505
|
+
case 'type-size': {
|
|
506
|
+
const constant = evalContext.constants.get(expression.typeExpr.name);
|
|
507
|
+
if (constant !== undefined) {
|
|
508
|
+
return constant;
|
|
509
|
+
}
|
|
510
|
+
return evaluateExpression(expression, {}, new Map(), silentSpan, [], {
|
|
511
|
+
currentLocation: 0,
|
|
512
|
+
layouts: evalContext.layouts,
|
|
513
|
+
reportUnknown: false,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
case 'offset':
|
|
394
517
|
case 'sizeof':
|
|
395
518
|
return evaluateExpression(expression, {}, new Map(), silentSpan, [], {
|
|
396
519
|
currentLocation: 0,
|
|
397
520
|
layouts: evalContext.layouts,
|
|
398
521
|
reportUnknown: false,
|
|
399
522
|
});
|
|
523
|
+
case 'byte-function': {
|
|
524
|
+
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
525
|
+
if (value === undefined) {
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
529
|
+
}
|
|
400
530
|
case 'unary': {
|
|
401
531
|
const value = evaluateLoweredConstant(expression.expression, evalContext);
|
|
402
532
|
if (value === undefined) {
|
|
@@ -446,12 +576,83 @@ function evaluateLoweredConstant(expression, evalContext) {
|
|
|
446
576
|
return undefined;
|
|
447
577
|
}
|
|
448
578
|
}
|
|
579
|
+
function evaluateLoweredResolvedConstant(expression, evalContext) {
|
|
580
|
+
switch (expression.kind) {
|
|
581
|
+
case 'symbol':
|
|
582
|
+
return evalContext.symbols.get(expression.name);
|
|
583
|
+
case 'unary': {
|
|
584
|
+
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
585
|
+
if (value === undefined) {
|
|
586
|
+
return undefined;
|
|
587
|
+
}
|
|
588
|
+
switch (expression.operator) {
|
|
589
|
+
case '+':
|
|
590
|
+
return value;
|
|
591
|
+
case '-':
|
|
592
|
+
return -value;
|
|
593
|
+
case '~':
|
|
594
|
+
return ~value;
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
case 'binary': {
|
|
599
|
+
const left = evaluateLoweredResolvedConstant(expression.left, evalContext);
|
|
600
|
+
const right = evaluateLoweredResolvedConstant(expression.right, evalContext);
|
|
601
|
+
if (left === undefined || right === undefined) {
|
|
602
|
+
return undefined;
|
|
603
|
+
}
|
|
604
|
+
switch (expression.operator) {
|
|
605
|
+
case '+':
|
|
606
|
+
return left + right;
|
|
607
|
+
case '-':
|
|
608
|
+
return left - right;
|
|
609
|
+
case '*':
|
|
610
|
+
return left * right;
|
|
611
|
+
case '/':
|
|
612
|
+
return right === 0 ? undefined : Math.trunc(left / right);
|
|
613
|
+
case '%':
|
|
614
|
+
return right === 0 ? undefined : left % right;
|
|
615
|
+
case '&':
|
|
616
|
+
return left & right;
|
|
617
|
+
case '^':
|
|
618
|
+
return left ^ right;
|
|
619
|
+
case '|':
|
|
620
|
+
return left | right;
|
|
621
|
+
case '<<':
|
|
622
|
+
return left << right;
|
|
623
|
+
case '>>':
|
|
624
|
+
return left >> right;
|
|
625
|
+
}
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
case 'byte-function': {
|
|
629
|
+
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
630
|
+
if (value === undefined) {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
634
|
+
}
|
|
635
|
+
default:
|
|
636
|
+
return evaluateLoweredConstant(expression, evalContext);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
449
639
|
function formatLoweredNumber(value, width) {
|
|
450
640
|
const normalized = value < 0 ? 0x10000 + (value & 0xffff) : value;
|
|
451
641
|
const digits = normalized.toString(16).toUpperCase();
|
|
452
642
|
const minWidth = width === 'word' || (width === 'auto' && normalized > 0xff) ? 4 : 2;
|
|
453
643
|
return `$${digits.padStart(minWidth, '0')}`;
|
|
454
644
|
}
|
|
645
|
+
function formatRotateShift(instruction, evalContext) {
|
|
646
|
+
const operand = formatBitOperand(instruction.operand, evalContext);
|
|
647
|
+
if (operand === undefined) {
|
|
648
|
+
return undefined;
|
|
649
|
+
}
|
|
650
|
+
const parts = [operand];
|
|
651
|
+
if (instruction.destination) {
|
|
652
|
+
parts.push(instruction.destination.register);
|
|
653
|
+
}
|
|
654
|
+
return { text: `${instruction.mnemonic} ${parts.join(', ')}` };
|
|
655
|
+
}
|
|
455
656
|
function formatBitOp(instruction, evalContext) {
|
|
456
657
|
const bit = formatLoweredNumber(instruction.bit, 'byte');
|
|
457
658
|
const operand = formatBitOperand(instruction.operand, evalContext);
|
|
@@ -5,6 +5,14 @@ import { autoFixableCandidateKeys } from './fix.js';
|
|
|
5
5
|
import { findCallerOutputCandidateObservations, findRegisterCareConflicts, } from './liveness.js';
|
|
6
6
|
import { buildAnnotations } from './annotations.js';
|
|
7
7
|
import { buildOutputCandidateFixability, buildProfileSummaries, buildProfileSummaryLookup, buildSummaries, buildSummaryByName, outputCandidateKey, routineNames, unknownBoundaryDiagnostics, unknownCallList, withAcceptedOutputs, } from './summaries.js';
|
|
8
|
+
function candidateMessageWithFixability(candidate, autoFixable) {
|
|
9
|
+
const carriers = candidate.carriers.join(',');
|
|
10
|
+
const expectation = candidate.carriers.length === 1 ? candidate.carriers[0] : `{${carriers}}`;
|
|
11
|
+
const base = `CALL ${candidate.routine} writes ${carriers} and caller reads it later`;
|
|
12
|
+
return autoFixable
|
|
13
|
+
? `${base}; generated contracts promote this to \`out ${expectation}\` automatically.`
|
|
14
|
+
: `${base}; manual review required before adding \`; expects out ${expectation}\` because the later read is not a simple direct continuation.`;
|
|
15
|
+
}
|
|
8
16
|
export function analyzeRegisterCare(loaded, options) {
|
|
9
17
|
const file = loaded.program.files[0];
|
|
10
18
|
const items = file?.items ?? [];
|
|
@@ -16,8 +24,8 @@ export function analyzeRegisterCare(loaded, options) {
|
|
|
16
24
|
contractMap.set(contract.name, contract);
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
|
-
let summaries = buildSummaries(program.routines, contractMap);
|
|
20
27
|
const profileSummaries = buildProfileSummaries(options.registerCareProfile);
|
|
28
|
+
let summaries = buildSummaries(program.routines, contractMap, profileSummaries);
|
|
21
29
|
summaries = withAcceptedOutputs(summaries, options.acceptedOutputCandidates);
|
|
22
30
|
const allSummaries = [...summaries, ...profileSummaries];
|
|
23
31
|
const summariesByName = buildSummaryByName(program.routines, summaries, profileSummaries);
|
|
@@ -41,10 +49,14 @@ export function analyzeRegisterCare(loaded, options) {
|
|
|
41
49
|
const conflicts = analyzed.conflicts;
|
|
42
50
|
const outputCandidates = analyzed.outputCandidates;
|
|
43
51
|
const outputCandidateFixability = buildOutputCandidateFixability(program.routines, outputCandidates, autoFixableCandidateKeys);
|
|
44
|
-
const outputCandidatesWithFixability = outputCandidates.map((candidate) =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
const outputCandidatesWithFixability = outputCandidates.map((candidate) => {
|
|
53
|
+
const autoFixable = outputCandidateFixability.get(outputCandidateKey(candidate.file, candidate.line, candidate.column)) ?? false;
|
|
54
|
+
return {
|
|
55
|
+
...candidate,
|
|
56
|
+
autoFixable,
|
|
57
|
+
message: candidateMessageWithFixability(candidate, autoFixable),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
48
60
|
if (options.mode !== 'audit') {
|
|
49
61
|
for (const conflict of conflicts) {
|
|
50
62
|
diagnostics.push({
|
|
@@ -58,7 +70,7 @@ export function analyzeRegisterCare(loaded, options) {
|
|
|
58
70
|
}
|
|
59
71
|
}
|
|
60
72
|
if (options.mode === 'strict') {
|
|
61
|
-
diagnostics.push(...unknownBoundaryDiagnostics(program.
|
|
73
|
+
diagnostics.push(...unknownBoundaryDiagnostics(program.directBoundaries, knownRoutines));
|
|
62
74
|
}
|
|
63
75
|
const reportModel = {
|
|
64
76
|
entryFile: loaded.program.entryFile,
|
|
@@ -67,10 +79,26 @@ export function analyzeRegisterCare(loaded, options) {
|
|
|
67
79
|
conflicts,
|
|
68
80
|
outputCandidates: outputCandidatesWithFixability,
|
|
69
81
|
...(options.registerCareProfile !== undefined ? { profile: options.registerCareProfile } : {}),
|
|
70
|
-
unknownCalls: options.mode === 'off' ? [] : unknownCallList(program.
|
|
82
|
+
unknownCalls: options.mode === 'off' ? [] : unknownCallList(program.directBoundaries, knownRoutines),
|
|
71
83
|
};
|
|
84
|
+
const summariesForAnnotations = new Map(summariesByName);
|
|
85
|
+
const outputCandidatesByRoutine = new Map();
|
|
86
|
+
for (const candidate of outputCandidatesWithFixability) {
|
|
87
|
+
const existing = outputCandidatesByRoutine.get(candidate.routine) ?? [];
|
|
88
|
+
for (const unit of candidate.carriers) {
|
|
89
|
+
if (!existing.includes(unit))
|
|
90
|
+
existing.push(unit);
|
|
91
|
+
}
|
|
92
|
+
outputCandidatesByRoutine.set(candidate.routine, existing);
|
|
93
|
+
}
|
|
94
|
+
for (const [name, summary] of summariesForAnnotations) {
|
|
95
|
+
const candidates = outputCandidatesByRoutine.get(name);
|
|
96
|
+
if (candidates !== undefined && candidates.length > 0) {
|
|
97
|
+
summariesForAnnotations.set(name, { ...summary, outputCandidates: candidates });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
72
100
|
const annotations = options.emitAnnotations
|
|
73
|
-
? buildAnnotations(loaded, program.routines,
|
|
101
|
+
? buildAnnotations(loaded, program.routines, summariesForAnnotations, outputCandidatesWithFixability, {
|
|
74
102
|
fixOutputCandidates: options.fixRegisterContracts === true,
|
|
75
103
|
outputCandidateFixability,
|
|
76
104
|
outputCandidateKey,
|
|
@@ -1,154 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return units.length === 1 ? units[0] : `{${units.join(',')}}`;
|
|
6
|
-
}
|
|
7
|
-
function formatCarrierLineWithExpectOut(indentation, units) {
|
|
8
|
-
return `${indentation}; expects out ${formatCandidateUnits(units)}`;
|
|
9
|
-
}
|
|
10
|
-
function formatCarrierLineWithMaybeOut(indentation, units) {
|
|
11
|
-
return `${indentation};! ${'maybe-out'.padEnd(10)}${formatCandidateUnits(units)}`;
|
|
12
|
-
}
|
|
13
|
-
function isGeneratedRegisterContractLine(line) {
|
|
14
|
-
return /^\s*;!\s*(in|out|clobbers|preserves|maybe-out)\b/i.test(line);
|
|
15
|
-
}
|
|
16
|
-
function isOutputCandidateHintLine(line) {
|
|
17
|
-
return /^\s*;\s*expects\s+out\b/i.test(line) || /^\s*;\s*!\s*maybe-out\b/i.test(line);
|
|
18
|
-
}
|
|
19
|
-
function normalizeLineEnding(text) {
|
|
20
|
-
return text.replace(/\r\n/g, '\n');
|
|
21
|
-
}
|
|
22
|
-
function splitSourceLines(text) {
|
|
23
|
-
return normalizeLineEnding(text).split('\n');
|
|
24
|
-
}
|
|
25
|
-
function lineDeltaForCandidate(line, deltas) {
|
|
26
|
-
let shift = 0;
|
|
27
|
-
for (const delta of deltas) {
|
|
28
|
-
if (delta.anchorLine < line) {
|
|
29
|
-
shift += delta.delta;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return shift;
|
|
33
|
-
}
|
|
34
|
-
function applyOutputCandidateHints(sourceText, outputCandidates, candidateFixability, deltas, outputCandidateKey) {
|
|
35
|
-
const lines = splitSourceLines(sourceText);
|
|
36
|
-
const grouped = new Map();
|
|
37
|
-
for (const candidate of outputCandidates) {
|
|
38
|
-
const adjustedLine = candidate.line + lineDeltaForCandidate(candidate.line, deltas);
|
|
39
|
-
const existing = grouped.get(adjustedLine);
|
|
40
|
-
const autoFixable = candidateFixability.get(outputCandidateKey(candidate.file, candidate.line, candidate.column)) ?? false;
|
|
41
|
-
if (existing === undefined) {
|
|
42
|
-
grouped.set(adjustedLine, { carriers: [...candidate.carriers], autoFixable });
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
const carriers = existing.carriers;
|
|
46
|
-
for (const carrier of candidate.carriers) {
|
|
47
|
-
if (!carriers.includes(carrier)) {
|
|
48
|
-
carriers.push(carrier);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
existing.autoFixable = existing.autoFixable && autoFixable;
|
|
52
|
-
}
|
|
53
|
-
const candidates = [...grouped.entries()]
|
|
54
|
-
.map(([line, entry]) => ({ line, ...entry }))
|
|
55
|
-
.sort((left, right) => right.line - left.line);
|
|
56
|
-
for (const candidate of candidates) {
|
|
57
|
-
const index = candidate.line - 1;
|
|
58
|
-
if (index < 0 || index > lines.length)
|
|
59
|
-
continue;
|
|
60
|
-
if (index > 0 && isOutputCandidateHintLine(lines[index - 1] ?? ''))
|
|
61
|
-
continue;
|
|
62
|
-
const indentation = lines[index]?.match(/^\s*/)?.[0] ?? '';
|
|
63
|
-
const hint = candidate.autoFixable
|
|
64
|
-
? formatCarrierLineWithExpectOut(indentation, candidate.carriers)
|
|
65
|
-
: formatCarrierLineWithMaybeOut(indentation, candidate.carriers);
|
|
66
|
-
lines.splice(index, 0, hint);
|
|
67
|
-
}
|
|
68
|
-
return lines.join('\n');
|
|
69
|
-
}
|
|
70
|
-
function annotateSourceFile(sourceText, routines, summariesByName) {
|
|
71
|
-
const routineLines = Array.from(routines)
|
|
1
|
+
import { annotateRegisterCareContracts } from './annotate.js';
|
|
2
|
+
import { applyExpectOutFixesToSource, findExpectOutFixesForCandidates, } from './fix.js';
|
|
3
|
+
export function buildAnnotations(loaded, programRoutines, summariesByName, outputCandidates, options) {
|
|
4
|
+
const routines = programRoutines
|
|
72
5
|
.filter((routine) => summariesByName.has(routine.name))
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const summary = summariesByName.get(routine.name);
|
|
81
|
-
if (!summary)
|
|
82
|
-
continue;
|
|
83
|
-
const insertLine = routine.span.start.line - 1;
|
|
84
|
-
if (insertLine < 0 || insertLine > lines.length)
|
|
85
|
-
continue;
|
|
86
|
-
const generatedLines = [
|
|
87
|
-
...(summary.mayRead.length > 0 ? [formatCarrierLine('in', summary.mayRead)] : []),
|
|
88
|
-
...(summary.mayWrite.length > 0 ? [formatCarrierLine('out', summary.mayWrite)] : []),
|
|
89
|
-
...(summary.preserved.length > 0 ? [formatCarrierLine('preserves', summary.preserved)] : []),
|
|
90
|
-
];
|
|
91
|
-
if (generatedLines.length === 0)
|
|
92
|
-
continue;
|
|
93
|
-
let start = insertLine;
|
|
94
|
-
for (let index = insertLine - 1; index >= 0 && isGeneratedRegisterContractLine(lines[index] ?? ''); index -= 1) {
|
|
95
|
-
start = index;
|
|
96
|
-
}
|
|
97
|
-
if (start === insertLine ||
|
|
98
|
-
lines.slice(start, insertLine).some((line) => line.trim().length === 0)) {
|
|
99
|
-
start = insertLine;
|
|
100
|
-
}
|
|
101
|
-
const existing = lines.slice(start, insertLine);
|
|
102
|
-
if (existing.length !== generatedLines.length ||
|
|
103
|
-
existing.some((line, index) => line !== generatedLines[index])) {
|
|
104
|
-
changed = true;
|
|
105
|
-
deltas.push({
|
|
106
|
-
anchorLine: routine.span.start.line,
|
|
107
|
-
delta: generatedLines.length - (insertLine - start),
|
|
108
|
-
});
|
|
109
|
-
lines.splice(start, insertLine - start, ...generatedLines);
|
|
110
|
-
}
|
|
6
|
+
.map((routine) => ({
|
|
7
|
+
routine,
|
|
8
|
+
summary: summariesByName.get(routine.name),
|
|
9
|
+
}));
|
|
10
|
+
const annotated = annotateRegisterCareContracts(loaded.sourceTexts, routines);
|
|
11
|
+
if (!options.fixOutputCandidates) {
|
|
12
|
+
return annotated.map((file) => ({ path: file.path, text: file.text }));
|
|
111
13
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
text:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const byFile = new Map();
|
|
121
|
-
for (const routine of programRoutines) {
|
|
122
|
-
if (!summariesByName.has(routine.name))
|
|
123
|
-
continue;
|
|
124
|
-
const file = byFile.get(routine.span.file);
|
|
125
|
-
if (file === undefined) {
|
|
126
|
-
byFile.set(routine.span.file, [routine]);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
file.push(routine);
|
|
130
|
-
}
|
|
14
|
+
const autoFixableCandidates = outputCandidates.filter((candidate) => options.outputCandidateFixability.get(options.outputCandidateKey(candidate.file, candidate.line, candidate.column)) === true);
|
|
15
|
+
const fixes = findExpectOutFixesForCandidates([...programRoutines], autoFixableCandidates);
|
|
16
|
+
if (fixes.length === 0) {
|
|
17
|
+
return annotated.map((file) => ({ path: file.path, text: file.text }));
|
|
18
|
+
}
|
|
19
|
+
const workingTexts = new Map(loaded.sourceTexts);
|
|
20
|
+
for (const file of annotated) {
|
|
21
|
+
workingTexts.set(file.path, file.text);
|
|
131
22
|
}
|
|
132
23
|
const out = [];
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
24
|
+
const fixesByFile = new Map();
|
|
25
|
+
for (const fix of fixes) {
|
|
26
|
+
const items = fixesByFile.get(fix.file) ?? [];
|
|
27
|
+
items.push(fix);
|
|
28
|
+
fixesByFile.set(fix.file, items);
|
|
29
|
+
}
|
|
30
|
+
for (const [path, text] of workingTexts) {
|
|
31
|
+
const reference = loaded.sourceTexts.get(path);
|
|
32
|
+
if (reference === undefined)
|
|
136
33
|
continue;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
text = annotation.text;
|
|
142
|
-
deltas = annotation.deltas;
|
|
143
|
-
}
|
|
144
|
-
if (options.fixOutputCandidates) {
|
|
145
|
-
const candidatesForFile = outputCandidates.filter((candidate) => candidate.file === path);
|
|
146
|
-
if (candidatesForFile.length > 0) {
|
|
147
|
-
text = applyOutputCandidateHints(text, candidatesForFile, options.outputCandidateFixability, deltas, options.outputCandidateKey);
|
|
148
|
-
}
|
|
34
|
+
const fileFixes = fixesByFile.get(path) ?? [];
|
|
35
|
+
const nextText = fileFixes.length > 0 ? applyExpectOutFixesToSource(text, fileFixes, reference) : text;
|
|
36
|
+
if (nextText !== reference) {
|
|
37
|
+
out.push({ path, text: nextText });
|
|
149
38
|
}
|
|
150
|
-
if (text !== sourceText)
|
|
151
|
-
out.push({ path, text });
|
|
152
39
|
}
|
|
153
|
-
return out;
|
|
40
|
+
return out.sort((left, right) => left.path.localeCompare(right.path));
|
|
154
41
|
}
|
|
@@ -6,4 +6,6 @@ export interface RegisterCareExpectOutFix {
|
|
|
6
6
|
routine: string;
|
|
7
7
|
carriers: RegisterCareUnit[];
|
|
8
8
|
}
|
|
9
|
+
export declare function findExpectOutFixesForCandidates(routines: RegisterCareRoutine[], candidates: RegisterCareOutputCandidate[]): RegisterCareExpectOutFix[];
|
|
9
10
|
export declare function autoFixableCandidateKeys(routines: RegisterCareRoutine[], candidates: RegisterCareOutputCandidate[]): Set<string>;
|
|
11
|
+
export declare function applyExpectOutFixesToSource(source: string, fixes: RegisterCareExpectOutFix[], referenceSource?: string): string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getZ80InstructionEffect } from '../z80/effects.js';
|
|
2
2
|
import { instructionSuccessors, labelIndex } from './controlFlow.js';
|
|
3
|
+
import { contractCarrierList } from './report.js';
|
|
4
|
+
import { joinSourceLines, splitSourceLines } from './sourceText.js';
|
|
3
5
|
function sameLocation(a, b) {
|
|
4
6
|
return a.file === b.file && a.line === b.line && a.column === b.column;
|
|
5
7
|
}
|
|
@@ -68,6 +70,9 @@ function findExpectOutFixes(routines, candidates) {
|
|
|
68
70
|
}
|
|
69
71
|
return out;
|
|
70
72
|
}
|
|
73
|
+
export function findExpectOutFixesForCandidates(routines, candidates) {
|
|
74
|
+
return findExpectOutFixes(routines, candidates);
|
|
75
|
+
}
|
|
71
76
|
export function autoFixableCandidateKeys(routines, candidates) {
|
|
72
77
|
const fixes = findExpectOutFixes(routines, candidates);
|
|
73
78
|
const out = new Set();
|
|
@@ -76,3 +81,50 @@ export function autoFixableCandidateKeys(routines, candidates) {
|
|
|
76
81
|
}
|
|
77
82
|
return out;
|
|
78
83
|
}
|
|
84
|
+
function isExpectOutLine(line) {
|
|
85
|
+
return /^\s*;\s*expects\s+out\b/i.test(line);
|
|
86
|
+
}
|
|
87
|
+
function expectedCallLine(originalLines, fix) {
|
|
88
|
+
return originalLines[fix.line - 1]?.trim();
|
|
89
|
+
}
|
|
90
|
+
function findCallLineIndex(lines, originalLines, fix) {
|
|
91
|
+
const expected = expectedCallLine(originalLines, fix);
|
|
92
|
+
if (!expected)
|
|
93
|
+
return undefined;
|
|
94
|
+
const preferred = fix.line - 1;
|
|
95
|
+
if (lines[preferred]?.trim() === expected)
|
|
96
|
+
return preferred;
|
|
97
|
+
let best;
|
|
98
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
99
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
100
|
+
if (lines[index]?.trim() !== expected)
|
|
101
|
+
continue;
|
|
102
|
+
const distance = Math.abs(index - preferred);
|
|
103
|
+
if (distance < bestDistance) {
|
|
104
|
+
best = index;
|
|
105
|
+
bestDistance = distance;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return best;
|
|
109
|
+
}
|
|
110
|
+
function indentation(line) {
|
|
111
|
+
return line.match(/^\s*/)?.[0] ?? '';
|
|
112
|
+
}
|
|
113
|
+
export function applyExpectOutFixesToSource(source, fixes, referenceSource = source) {
|
|
114
|
+
if (fixes.length === 0)
|
|
115
|
+
return source;
|
|
116
|
+
const originalLines = referenceSource.split(/\r?\n/);
|
|
117
|
+
const sourceLines = splitSourceLines(source);
|
|
118
|
+
const { lines } = sourceLines;
|
|
119
|
+
const sorted = [...fixes].sort((a, b) => b.line - a.line || b.column - a.column);
|
|
120
|
+
for (const fix of sorted) {
|
|
121
|
+
const index = findCallLineIndex(lines, originalLines, fix);
|
|
122
|
+
if (index === undefined)
|
|
123
|
+
continue;
|
|
124
|
+
if (index > 0 && isExpectOutLine(lines[index - 1] ?? ''))
|
|
125
|
+
continue;
|
|
126
|
+
const prefix = indentation(lines[index] ?? '');
|
|
127
|
+
lines.splice(index, 0, `${prefix}; expects out ${contractCarrierList(fix.carriers)}`);
|
|
128
|
+
}
|
|
129
|
+
return joinSourceLines(sourceLines);
|
|
130
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Z80Instruction, Z80Operand } from '../z80/instruction.js';
|
|
2
|
+
import type { RegisterCareInstruction } from './types.js';
|
|
3
|
+
export declare function instructionHead(item: RegisterCareInstruction): string;
|
|
4
|
+
export declare function regName(operand: Z80Operand | undefined): string | undefined;
|
|
5
|
+
export declare function instructionOperandCount(instruction: Z80Instruction): number;
|
|
6
|
+
export declare function instructionOperand(instruction: Z80Instruction, index: number): Z80Operand | undefined;
|
|
7
|
+
export declare function isUnconditionalReturnInstruction(item: RegisterCareInstruction): boolean;
|
|
8
|
+
export declare function isPureTokenTransferInstruction(item: RegisterCareInstruction): boolean;
|
|
9
|
+
export declare function isAccumulatorSelfOperand(item: RegisterCareInstruction): boolean;
|
|
10
|
+
export declare function isImmediateZeroOperand(item: RegisterCareInstruction): boolean;
|
|
11
|
+
export declare function isRegisterOperand(item: RegisterCareInstruction | undefined, index: number, name: string): boolean;
|